JAVA SM2 数字证书生成

2023-11-18

Before Start

X.509数字证书请参考:

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

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

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

Build with Maven

<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编码的字符串,我们能够快速分析证书的结构,以及各种字段。
截图

致谢

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

参考列表:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA SM2 数字证书生成 的相关文章

随机推荐

  • javascript中Math.random()产生随机数及parseInt的作用

    Math random 是令系统随机选取大于等于 0 0 且小于 1 0 的小数 即 0 0 1 0 Math floor 返回小于参数x的最大整数 即对浮点数向下取整 比如Math floor 3 8 为3 一 在连续整数中取得一个随机整
  • WIN10 系统的 IRQL NOT LESS OR EQUAL 蓝屏问题

    WIN10 系统的 IRQL NOT LESS OR EQUAL 蓝屏问题 请参考以下步骤 1 Win r 输入 msconfig 2 点击 服务 标签卡 选择 隐藏所有的微软服务 然后点击全部禁用 若您启用了指纹识别功能 请不要关闭相关服
  • c#基础知识---多线程

    线程 被定义为程序的执行路径 每个线程都定义了一个独特的控制流 如果您的应用程序涉及到复杂的和耗时的操作 那么设置不同的线程执行路径往往是有益的 每个线程执行特定的工作 线程是轻量级进程 一个使用线程的常见实例是现代操作系统中并行编程的实现
  • Windows11 安装 WSA 简单上手一试

    Win11 安装 WSA 安卓子系统 教程 参考 http www xitongzhijia net xtjc 20211008 228813 html 上手需要一些 命令行 基础 大概了解 WSL WSA Hyper V 等概念 微软尚未
  • 模糊控制规则表是怎么确定的_模糊控制

    1 模糊控制的基本原理 模糊控制是以模糊集理论 模糊语言变量和模糊逻辑推理为基础的一种智能控制方法 它是从行为上模仿人的模糊推理和决策过程的一种智能控制方法 该方法首先将操作人员或专家经验编成模糊规则 然后将来自传感器的实时信号模糊化 将模
  • 空洞卷积(Atrous convolution)

    目录 空洞卷积 空洞卷积优点 Dilated Convolution存在的问题 空洞卷积 空洞卷积是针对图像语义分割问题中下采样会降低图像分辨率 丢失信息而提出的一种卷积思路 利用添加空洞扩大感受野 让原本3x3的卷积核 在相同参数量和计算
  • PyQt5模块构成

  • c语言求数字b在a中出现次数,编写一个函数void fun(char *tt,int pp[]),统计在tt字符中"a"到"z"26各字母各自出现的次数,并依次放在pp所指的数组中。...

    满意答案 yjj0h044 2015 09 26 采纳率 50 等级 8 已帮助 961人 void fun char tt int pp int i for i 0 i 26 i pp i 0 while tt switch tt cas
  • Failed to execute ‘drawImage‘ on ‘CanvasRenderingContext2D‘: The image argument is a canvas element

    Echarts重绘报错 原因在于绘制时 未正确获取到画布的宽高 可在容器内写入行内样式 即可解决
  • 《Windows驱动开发技术详解》之读写操作

    缓冲区方式读写操作 设置缓冲区读写方式 读写操作一般是由ReadFile和WriteFile函数引起的 这里先以WriteFile函数为例进行介绍 WriteFile要求用户提供一段缓冲区 并且说明缓冲区的大小 然后WriteFile将这段
  • 前端将下载的文件压缩为zip文件

    本来的话这个前端下载文件是要从后端的接口获取二进制流数据 再进行操作的 但是懒得自己写接口返回二进制流数据 就用了比较偷懒的方法来模拟这个二进制流数据 直接用原生的input就可以 类型选择为file 然后点击这个input 就可以拿到fi
  • 河北专接本微机原理错题整理及资料分享

    菜鸡经验分享 ps 我是边上班边接本总分352 专业课发挥失误 哎 专业微机原理没技巧就是背 多背多刷题 资料中的15套题多刷几遍 视频看b站鸡哥的就行 数学98 哪年考的都不难题型都差不多 资料中的卷子多刷刷就行 刷的时候必须满分 英语2
  • MYSQL的索引使用注意

    索引并不是时时都会生效的 比如以下几种情况 将导致索引失效 最左前缀法则 如果使用了联合索引 要遵守最左前缀法则 最左前缀法则指的是查询从索引的最左列开始 并且不跳过索引中的列 如果跳跃某一列 索引将会部分失效 后面的字段索引失效 查看tb
  • 牛客网华为OD前端岗位,面试题库练习记录02

    题目一 删除字符串中出现次数最少的字符 HJ23 JavaScript Node ACM 模式 const rl require readline createInterface input process stdin var iter r
  • php简单的网站CRUD功能

    编辑器 使用的phpstrom 环境使用的 xampp 前段掌握并不熟练 引用了jQuery和bootstrap 目录 主页 数据库连接conn php home html 登录处理模块login php 登陆后可进入页面index php
  • 桥接模式下的虚拟机中ping不通网关

    桥接的虚拟机ping不通网关 配置VM 工具栏中的 编辑 gt 虚拟网络编辑器 点击添加网络 再选择桥接模式 2 打开虚拟机设置 网络适配器选择桥接模式 4 进入虚拟机 进入网络配置 5 将宿机的IP 掩码 网关等信息配置 注意 此时选择
  • angular新建组件的组成部分

    主要分为三个组成部分 一 一个ts文件 用来处理数据和功能的 初始会有一个inport 和一个 component 二 一个html文件 用来书写页面的内容 初始会有一个标签 三 一个css文件 用来书写页面样式 初始是一个空文件夹 转载于
  • redis 主从哨兵模式搭建

    一 REDIS主从模式 搭建三个节点 同一个机器 三个端口 安装包 wget http download redis io releases redis 5 0 7 tar gz 安装步骤 https blog csdn net whg18
  • 【Linux】Linux和Window下\r与\n的区别、git命令行的使用

    作者 小卢 专栏 Linux Git 喜欢的话 世间因为少年的挺身而出 而更加瑰丽 人民日报 目录 1 回车换行符在Window下和在Linux下的区别 1 1回车换行符 1 2 行缓冲区打印 1 3进度条小程序 2 git命令行的使用 2
  • JAVA SM2 数字证书生成

    文章目录 Before Start Build with Maven QuickStart 生成自签名公私钥对 证书签名算法算法提供者 设置证书信息 标识信息构造 DN 获取扩展密钥用途构造 可选 证书信息构造 X 509格式证书对象生成