文章目录

  • Before Start
    • Build with Maven
  • QuickStart
    • 生成自签名公私钥对
    • 证书签名算法算法提供者
    • 设置证书信息
      • 标识信息构造(DN)
      • 获取扩展密钥用途构造(可选)
      • 证书信息构造
      • X.509格式证书对象生成
      • 保存证书
    • ASN.1 结构解析工具
  • 致谢

Before Start

X.509数字证书请参考:

RFC5280 Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile

中文版的简要介绍可以参考这篇文章 Agzs . X509证书–ANS1结构

如果还未能生成SM2密钥对请先阅读

  • JAVA SM2 密钥生成 签名验签

Build with Maven

  • bcprov
  • bcpkix
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.60</version>
</dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.60</version>
</dependency>

QuickStart

Github

/*** BouncyCastle算法提供者*/
private static final Provider BC = new BouncyCastleProvider();

生成自签名公私钥对

keyPairGenerator的构造请参考 JAVA SM2 密钥生成 签名验签

// 产生密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();

证书签名算法算法提供者

在制作证书时需要使用到签名算法签名证书中部分数据区域,国密类型的数字证书使用的签名算法是SM3withSM2,这里使用私钥创建算法提供容器。

ContentSigner sigGen = new JcaContentSignerBuilder("SM3withSM2").setProvider(BC).build(keyPair.getPrivate());

设置证书信息

设置证书的基本数据:使用者信息、颁发者信息、证书序号、证书生效日期、证书失效日期,以及证书扩展属性。

标识信息构造(DN)

上面提到的使用者信息、颁发者信息,使用Distinct Name的方式来描述。

关于DN中的各个字段的含义请参考 IBM Previous Next
Distinguished Names

实际上简单来讲就是,用来确定“实体” 身份/信息 的一系列列键值对组成的字符串。

这里的键是一个ASN1ObjectIdentifier,实际上Bouncycastle已经为我们把需要的大多键都已经列好了,我们只要使用这个类org.bouncycastle.asn1.x500.style.BCStyle的静态变量就可以。

private static X500NameBuilder createStdBuilder() {X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);// 国家代码builder.addRDN(BCStyle.C, "CN");// 组织builder.addRDN(BCStyle.O, "HZNU");// 省份builder.addRDN(BCStyle.ST, "Zhejiang");// 地区builder.addRDN(BCStyle.L, "Hangzhou");return builder;
}

然后我们就可以使用X500NameBuilderbuild()方法构造对应的DN了。

BCStyle 源码请参考,也可以使用与该文件中处于同级目录的RFC4519Style

获取扩展密钥用途构造(可选)

如果需要设置证书的扩展密钥用途,可以使用DERSequence来构造一个拓展密钥用途的序列。

拓展密钥用途

public static DERSequence extendedKeyUsage() {// 构造容器对象ASN1EncodableVector vector = new ASN1EncodableVector();// 客户端身份认证vector.add(KeyPurposeId.id_kp_clientAuth);// 安全电子邮件vector.add(KeyPurposeId.id_kp_emailProtection);return new DERSequence(vector);
}

扩展密钥用途的各个OID Bouncycastle 已经为我们提供,请参考KeyPurposeId

证书信息构造

接下来可以使用X509v3CertificateBuilder 来设置证书的基本参数,下面列举基本一些证书参数和扩展参数的设置方式。

// 构造X.509 第3版的证书构建者
X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(// 颁发者信息createStdBuilder().build()// 证书序列号, BigInteger.valueOf(1)// 证书生效日期, new Date(System.currentTimeMillis() - 50 * 1000)// 证书失效日期, new Date(System.currentTimeMillis() + 50 * 1000)// 使用者信息(PS:由于是自签证书,所以颁发者和使用者DN都相同), createStdBuilder().build()// 证书公钥, keyPair.getPublic())/*设置证书扩展证书扩展属性,请根据需求设定,参数请参考 《RFC 5280》*/// 设置密钥用法.addExtension(Extension.keyUsage, false, new X509KeyUsage(X509KeyUsage.digitalSignature | X509KeyUsage.nonRepudiation))// 设置扩展密钥用法:客户端身份认证、安全电子邮件.addExtension(Extension.extendedKeyUsage, false, extendedKeyUsage())// 基础约束,标识是否是CA证书,这里false标识为实体证书.addExtension(Extension.basicConstraints, false, new BasicConstraints(false))// Netscape Cert Type SSL客户端身份认证.addExtension(MiscObjectIdentifiers.netscapeCertType, false, new NetscapeCertType(NetscapeCertType.sslClient));

更多 Netscape Cert Type 类型请参考:NetscapeCertType

X.509格式证书对象生成

通过使用证书构造好的信息,接下就能够生成x509格式的证书对象

// 将证书构造参数装换为X.509证书对象
X509Certificate certificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen));

保存证书

如果需要永久的保存刚才生成的这份证书,那么我们需要对这个证书进行序列化,常见的证书序列化是将ASN.1编码的证书对象,进行BASE64编码,这样证书更加便于网络传输。

public static void makeCertFile(X509Certificate x509Certificate, Path savePath) throws CertificateEncodingException, IOException {if (Files.exists(savePath)) {// 删除已存在文件Files.deleteIfExists(savePath);}// 创建文件Files.createFile(savePath);// 获取ASN.1编码的证书字节码byte[] asn1BinCert = x509Certificate.getEncoded();// 编码为BASE64 便于传输byte[] base64EncodedCert = Base64.encode(asn1BinCert);// 写入文件Files.write(savePath, base64EncodedCert);
}

给与文件名称,调用保存(常见的DER编码的证书后缀名为.cer)。

// 保存为证书文件
makeCertFile(certificate, Paths.get("test-cert.cer"));

ASN.1 结构解析工具

asn1js

通过该工具,输入证书的BASE64编码的字符串,我们能够快速分析证书的结构,以及各种字段。

致谢

在编写代码时参考了下面的例子:

  • Java Code Examples . X509v3CertificateBuilder.https://www.programcreek.com/java-api-examples/?api=org.bouncycastle.cert.X509v3CertificateBuilder
  • github . bouncycastle . https://github.com/bcgit/bc-java/blob/master/pkix/src/test/jdk1.1/org/bouncycastle/cert/test/CertTest.java

参考列表:

  • RFC5280 . Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile . https://tools.ietf.org/html/rfc5280)
  • Agzs . X509证书–ANS1结构 . https://blog.csdn.net/code_segment/article/details/77163652
  • IBM . Previous Next
    Distinguished Names . https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.sec.doc/q009860_.htm

JAVA SM2 数字证书生成相关推荐

  1. java中RSA数字证书生成,jks文件生成以及读取。

    一.Java代码生成cer证书文件: public class GetCertFile { //证书颁发者     static String CertificateIssuer = "C= ...

  2. java exchange 数字证书认证_java处理加密文件---数字证书文件格式(cer和pfx)的区别 - 数安时代(GDCA)SSL证书官网...

    java处理加密文件中常见的两种数字证书文件格式(cer和pfx) 数字证书文件格式(cer和pfx)的区别 1.带有私钥的证书 由Public Key Cryptography Standards ...

  3. java代码实现证书生成客户端证书 实现ssl双向认证

    目的:实现web项目的ssl双向认证客户端证书代码生成. 使用openssl生成ca证书和服务端证书,当然也可以通过代码实现 1)创建CA私钥,创建目录ca openssl genrsa -out c ...

  4. java对数字证书的验证_JAVA对数字证书的常用操作

    一:需要包含的包 import java.security.*; import java.io.*; import java.util.*; import java.security.*; impor ...

  5. java usbkey数字证书_Java创建数字证书

    BouncyCastle下载: 链接:http://pan.baidu.com/s/1vrcL4    密码:6i27 package com.what21.security05; import ja ...

  6. java usbkey数字证书_Java 密钥库和数字证书

    密钥库中可以存放多个条目(公钥/私钥对和证书),它们在密钥库中以别名(alias)区分. 1.cd C:\Program Files (x86)\Java\jdk1.6.0_10\bin 2.生成签名 ...

  7. java publickey_数字证书中读取PublicKey

    1. 读取https签发证书中的key 1) 在下面的代码中,是实现读取证书字符串来读取key的,CERTIFICATE 就是一个证书的字符串, 而方法cf.generateCertificate() ...

  8. 数字证书 - Java加密与安全

    数字证书我们在前面看到了一些计算机密码学的一些算法1. 摘要算法确保数据没有被篡改2. 非对称加密就是对数据进行加解密3. 数据签名可以确保数据完整性和抗否认性而数字证书就是集合了多种密码学算法,用于 ...

  9. 生成p12自签名数字证书使用p12证书为apk签名

    本文为本人实践并整理http://zengrong.net/post/1695.htm.http://blog.chinaunix.net/uid-20593721-id-4277435.html两篇 ...

最新文章

  1. Jenkins入门总结
  2. Android Device Monitor 文件管理的常见问题 - z
  3. USTC English Club Note20211215
  4. 很酷的word技巧---删除行前的空格
  5. 学习SQLSERVER2005高可用性数据库镜像的一些心得
  6. Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest 思维 + 差分
  7. 《Effective Java》读书笔记 Item 1:考虑静态工厂方法,而不是构造器
  8. rds基于什么开发_IaaS、PaaS、SaaS、DaaS都是什么?现在怎么样了?终于有人讲明白了...
  9. shell 脚本 自动化
  10. 【精彩实况】第三届大数据科学与工程国际会议
  11. 介绍一种 Python 更方便的爬虫代理池实现方案
  12. short s=1;s=s+1有问题吗?short s=1;s+=1;有问题吗?
  13. 趣闻|论文不必参考任何文献?看到作者,网友大呼失敬了
  14. 软件公司的管理规范化了、编制都齐全了,一般小公司是承受不了的这么庞大的开支的...
  15. 大公司笔试面试有哪些经典算法题目?
  16. Elasticsearch6.3.0安装Ansj分词插件
  17. 计算机哪个专业学linux_5种用于计算机维修的专业Linux发行版
  18. 5000张高清壁纸大图(手机用),用Python在法律的边缘又试探了一把
  19. 富士通scan按钮自动扫描设置
  20. python模块相互引用_python导入模块交叉引用的方法

热门文章

  1. 【web学习之Mysql】数据库-----查询操作------大全
  2. 舔砖加瓦(java)之java常用类
  3. 读《谁动了我的奶酪》---做一个新人
  4. 简单对象协议(SOAP)简介
  5. 握手,交流从掌心开始
  6. Linux学习2_Sinno_Song_新浪博客
  7. 16路彩灯控制器 FPGA-Verilog
  8. J2V8 -- 开始使用J2V8
  9. python strip()方法使用
  10. 足球竞赛规则的部分补充说明