Java生成SSL自签名证书及解析(keytool方式和源码方式)

发布时间 2023-07-23 17:42:57作者: 蚂蚁小哥

一:序

  当需要在 Java 应用程序中使用 SSL/TLS 加密通信或进行身份验证时,证书是必不可少的。证书可以用来验证服务器的身份,并确保通信的安全性。在 Java 开发中,可以使用 JDK 自带的 keytool 工具生成自签名证书。而本文将介绍如何使用 JDK 的 keytool 工具生成自签名证书以及相关操作。自签名证书适用于开发环境和内部测试,但不适用于生产环境。在正式发布应用程序或网站之前,建议使用受信任的证书颁发机构(CA)签署的证书。

1:环境及其它说明

  本文使用JDK1.8和JDK17在Window10环境来进行测试。

  在本章主要使用JDK自带的keytool工具进行创建自签名证书和解析自签名证书;再者使用Java代码的方式来构建自签名证书的创建和解析,并提供各式各样的方法用来公钥私钥的加密等等方法。

二:使用JDK自带keytool工具

  keytool为我们提供各式各样的命令,根据下面部分命令介绍;如下:

 -certreq            生成证书请求                 -changealias        更改条目的别名
 -delete             删除条目                    -exportcert         导出证书
 -genkeypair         生成密钥对                  -genseckey          生成密钥
 -gencert            根据证书请求生成证书          -importcert         导入证书或证书链
 -importpass         导入口令                    -importkeystore     从其他密钥库导入一个或所有条目
 -keypasswd          更改条目的密钥口令            -list               列出密钥库中的条目
 -printcert          打印证书内容                 -printcertreq       打印证书请求的内容
 -printcrl           打印 CRL 文件的内容          -storepasswd        更改密钥库的存储口令
 -showinfo           显示安全相关信息(JDK1.8没有)

1:生成密钥对 -genkeypair

  其实我们生成常用的密钥库类型有PKCS12、JKS;在正常的情况下推荐使用PKCS12

具体区别:
    PKCS12:PKCS12是一种通用的密钥库格式,它可以存储多个私钥、公钥和证书。它通常使用.p12或.pfx作为文件扩展名。
    JKS:JKS是Java特定的密钥库格式,由Java开发并广泛用于Java应用程序。它可以存储私钥,公钥和证书。它使用.jks作为文件扩展名。
密钥口令:
    PKCS12:PKCS12密钥库支持为每个私钥对设置单独的密钥口令,这意味着您可以为每个密钥对设置不同的密码。
    JKS:JKS密钥库不支持为每个私钥对设置单独的密钥口令,它使用一个密码来保护整个密钥库中的所有密钥和证书。
可移植性:
    PKCS12:PKCS12是一种通用的密钥库格式,广泛支持各种平台和应用程序。因此,PKCS12格式的密钥库在不同的系统和应用之间更易于导入和导出。
    JKS:JKS是Java特定的密钥库格式,主要用于Java应用程序。它在其他非Java平台上的支持可能有限。
对于大多数情况下,如果您的应用程序是基于Java的,建议使用JKS格式的密钥库。如果您需要与其他非Java系统进行交互或导入/导出密钥库,
则可以考虑使用PKCS12格式的密钥库。
PKCS12与JKS密钥库类型说明

生成PKCS12密钥库:

生成PKCS12类型密钥库:(注:复制时请保证不能换行)
    keytool -genkeypair -alias testAlias -keyalg RSA -keysize 2048 -sigalg SHA256withRSA 
   -dname "CN=antladdie.asia, OU=development, O=dianyan, L=luan, ST=anhui, C=china" -validity 10
   -storepass 123456 -keystore D:\certificate.p12 -v

命令说明:-genkeypair
    -alias <别名>:指定生成的密钥对的别名。别名是用于在密钥库中唯一标识密钥对的字符串
    -keyalg <算法>:指定生成密钥对所使用的算法。常用的算法包括 RSA、DSA和EC(椭圆曲线)。
    -keysize <大小>:指定生成密钥对的大小(以位为单位)。可以使用不同的密钥大小来提供不同级别的安全性。默认为2048。
    -sigalg <算法>:指定用于生成证书签名的算法。默认情况下,该算法与密钥算法相匹配。
        常用算法:
            SHA1withRSA: 使用 SHA-1 哈希算法和 RSA 密钥对进行签名
            SHA256withRSA: 使用 SHA-256 哈希算法和 RSA 密钥对进行签名
            SHA512withRSA: 使用 SHA-512 哈希算法和 RSA 密钥对进行签名
            SHA256withECDSA: 使用 SHA-256 哈希算法和椭圆曲线数字签名算法进行签名
            SHA512withECDSA: 使用 SHA-512 哈希算法和椭圆曲线数字签名算法进行签名
    -dname <DN>:指定生成证书时的主题信息。DN包含证书的各种信息,如国家/地区、组织、单位、通用名称等。
        C(国家)、ST(省份/州)、L(城市)、O(组织)、OU(部门)、CN(公司)
    -validity <天数>:指定生成的证书的有效期(以天为单位)。
    -storepass <密码>:指定密钥库的密码。该密码用于保护密钥库中的密钥和证书。
    -keystore <密钥库文件>:指定密钥库的位置和名称。密钥库是存储密钥对和证书的文件。
    -keypass <密码>:指定生成的密钥对的密码。该密码用于保护私钥(PKCS12下会忽略)。
注:CN为我们申请的域名信息,在这里我的是 antladdie.asia

Win10安装密钥库PKCS12:

  双击按照提示操作,并输入密钥库密码导入即可,若查看则:
  “管理用户证书”时按住Win + R 并输入 certmgr.msc 将打开“管理用户证书”窗口
  “管理计算机证书”时按住Win + R 并输入 certlm.msc 将打开“管理计算机证书”窗口

2:查看密钥库 -list

  比如查询上面生成的密钥库信息:keytool -list -v -keystore D:\certificate.p12 -storepass 123456

补充:密钥库(KeyStore)中,有三种不同类型的条目:SecretKeyEntry、PrivateKeyEntry和TrustedCertificateEntry;
它们分别表示不同的密钥和证书条目:
    SecretKeyEntry(对称密钥条目):表示一个对称密钥条目,用于存储对称密钥,如 AES、DES 等加密算法所使用的密钥。
        对称密钥是用于加密和解密数据的相同密钥,在 KeyStore 中以 SecretKey 的形式保存。
    PrivateKeyEntry(私钥条目):表示一个私钥条目,用于存储与之关联的私钥和相应的公钥证书。私钥用于进行数字签名和解密操作,
        与之关联的公钥证书用于验证签名和加密数据。私钥条目通常用于身份验证和安全通信,例如使用 RSA 或 ECC 算法的密钥对。
    TrustedCertificateEntry(受信任的证书条目):表示一个受信任的证书条目,用于存储已信任的证书。这些证书可以是自签名证书
        或由受信任的证书颁发机构(CA)签名的证书。受信任的证书条目通常用于建立信任链用于验证其他证书的有效性。
总结:SecretKeyEntry用于存储对称密钥,PrivateKeyEntry用于存储私钥和公钥证书,而TrustedCertificateEntry则用于存储受信任的证书。
这些条目类型在密钥库中具有不同的用途和功能,并且可以根据实际需求进行选择和使用。

3:证书提取 -exportcert

以之前生成的密钥库来提取 keytool -exportcert -alias testAlias -file D:\certificate.cer -storepass 123456 -keystore D:\certificate.p12

命令说明:
    -alias<别名>:要处理密钥库内的条目别名
    -file<文件>:提取后输出证书文件的位置及名称
    -keystore<密钥库>:密钥库文件的位置及名称
    -storetype<type>:当前密钥库的类型,如:JKS、PKCS12
    -storepass<密码>:访问密钥库的密码

4:修改密钥库密码 -storepasswd

以之前生成的密钥库来更换密码:
    keytool -storepasswd -new 88888888 -keystore D:\certificate.p12 -storepass 123456 -storetype PKCS12
命令说明:
    -new<密码>:新密码
    -keystore<密钥库>:密钥库文件的位置及名称
    -storetype<type>:当前密钥库的类型,如:JKS、PKCS12
    -storepass<密码>:访问密钥库的密码

5:更改条目别名 -changealias

以之前生成的密钥库来更换testAlias的别名为myalias:
    keytool -changealias -alias testAlias -destalias myalias -keystore D:\certificate.p12 -storepass 88888888 -storetype PKCS12
命令说明:
    -alias<别名>:要处理密钥库内的条目别名
    -destalias<别名>:修改指定名称的别名信息
    -keypass<口令>:密钥口令(若密钥库内的条目存在密码则需要输入条目密码,创建时尽可能保证和密钥库密码一致)
    -keystore<密钥库>:密钥库文件的位置及名称
    -storetype<type>:当前密钥库的类型,如:JKS、PKCS12
    -storepass<密码>:访问密钥库的密码

6:导入其它密钥库条目 -importkeystore

生成两个测试的密钥库,并且内部都存在一个密钥对:
    keytool -genkeypair -alias keya -keyalg RSA -dname "CN=xiao.asia, OU=development, O=dianyan, L=luan, ST=anhui, C=china" -validity 10 -storepass 123456 -keystore D:\demoa.p12
    keytool -genkeypair -alias keyb -keyalg RSA -dname "CN=yang.asia, OU=development, O=dianyan, L=luan, ST=anhui, C=china" -validity 10 -storepass 123456 -keystore D:\demob.p12
操作:demoa.p12内的keya别名密钥对导入到demob.p12内,并且导入后的别名变为keyaa
    keytool -importkeystore -srckeystore D:\demoa.p12 -destkeystore D:\demob.p12 -srcstoretype PKCS12 -deststoretype PKCS12 -srcstorepass 123456 -deststorepass 123456 -srcprotected -destprotected -srcalias keya -destalias keyaa
命令说明:(加粗的上两对和下两对互斥)
    -srckeystore <密钥库>:指定源密钥库的路径和文件名。
    -destkeystore <密钥库>:指定目标密钥库的路径和文件名。
    -srcstoretype <类型>:指定源密钥库的类型,例如JKS、PKCS12等。
    -deststoretype <类型>:指定目标密钥库的类型,例如JKS、PKCS12等。
    -srcstorepass <密码>:指定源密钥库的密码。如果未提供该参数且源密钥库设置了密码,命令行将提示您输入密码。
    -deststorepass <密码>:指定目标密钥库的密码。如果未提供该参数且目标密钥库设置了密码,命令行将提示您输入密码。
    -srcprotected:表示源密钥库的密码受保护。当此选项被使用时,命令行会提示您输入密码,并以不回显的方式进行输入。
    -destprotected:表示目标密钥库的密码受保护。当此选项被使用时,命令行会提示您输入密码,并以不回显的方式进行输入。
    -srcalias <别名>:指定要导入的源别名。如果未提供该参数,则默认选择源密钥库中第一个条目作为别名。
    -destalias <别名>:指定导入到目标密钥库的别名。如果未提供该参数,则使用源别名。
    -srckeypass <密码>:指定要导入的源密钥的密码。如果未提供该参数且源别名设置了密码,命令行将提示您输入密码。
    -destkeypass <密码>:指定导入到目标密钥库的密钥的密码。如果未提供该参数且源密钥设置了密码,命令行将提示您输入密码。
    -srcprovidername <名称>:指定源密钥库提供商的名称。
    -destprovidername <名称>:指定目标密钥库提供商的名称。

7:证书导入 -importcert

案例准备:通过最开始我们创建了certificate.p12密钥库,并且提取其内部证书到certificate.cer
操作:把certificate.cer导入到之前创建的demoa.p12密钥库内
    keytool -importcert -alias testcer -file D:\certificate.cer -keystore D:\demoa.p12 -storetype PKCS12 -storepass 123456
命令说明:
    -alias <别名>:指定导入的证书在目标密钥库内显示的条目别名信息
    -file <文件>:指定输入文件的名称。该选项用于在命令中指定要处理的文件路径和名称。可以是证书、私钥等相关的文件。
    -storepass <密码>:指定密钥库的口令。对于需要访问密钥库的操作,可以使用该选项来输入密钥库的密码。
    -storetype <类型>:指定密钥库的类型。用于指定要使用的密钥库的格式类型,例如JKS、PKCS12等。
    -keystore <密钥库名称>:指定密钥库的名称。用于指定要使用的密钥库文件的路径和名称。
    -keypass <密码>:指定密钥的口令。对于需要处理密钥的操作,可以使用该选项来输入密钥的密码。
    -noprompt:在执行命令时,不显示任何提示信息。
    -trustcacerts:表示信任导入的证书。
    -protected:通过受保护的机制输入密码。密码输入时不可见,这样可以提高密码的安全性,防止密码被他人窥视。

8:删除密钥库条目 -delete

  删除密钥库内指定条目:keytool -delete -alias keya -keystore D:\demoa.p12 -storetype PKCS12 -storepass 123456

9:修改密钥库内条目密码 -keypasswd

修改密钥库内的条目密码,通常修改PrivateKeyEntry类型的密码;注意:PKCS12类型无法使用-keypasswd
    keytool -keypasswd -alias myPrivateKeyAlias -keypass 1234567 -new 111222 -keystore D:\certificate.jks -storetype JKS -storepass 123456
命令说明:
    -alias<别名>:要处理密钥库内的条目别名
    -keypass<口令>:密钥库条目口令(若密钥库内的条目存在密码则需要输入条目密码)
    -new<口令>:新的密钥库内条目口令
    -keystore<密钥库>:密钥库文件的位置及名称
    -storetype<type>:当前密钥库的类型,如:JKS
    -storepass<密码>:访问密钥库的密码

三:使用编写的工具类代码的方式生成、解析、加密

  具体详细代码,代码内存在案例说明:密钥库工具类