Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Digital Certificate

downgoon edited this page Oct 17, 2017 · 3 revisions

数字证书 与 keystore 详解

密码在配置文件中明文存储不安全,于是JDK层面提供了keystore机制,它是一个特殊的文件,里面可以存储多个秘钥。为了保护信息安全,提供两级口令,一个是keystore文件级口令;另一个是秘钥口令(文件中可以存多个秘钥,每个秘钥可以有不同的口令)。

这个文件的后缀叫.jks,表示Java Key Store。管理它的工具叫keytool,JDK自带。

  • 秘钥:密码的高级形式。它的特点是:二进制不可显;很长。秘钥还分对称与非对称。
  • 证书:对于非对称的秘钥,私钥部分是不传递的,公钥是需要传播的。同时,公钥需要CA签名,被签名的公钥就是证书。

提供的功能

$ keytool
 // 创建秘钥,查看秘钥,删除秘钥
 -genkeypair 生成密钥对
 -delete 删除条目
 -list 列出密钥库中的条目
 -changealias 更改条目的别名
 // 两级口令管理:store级 与 key级
 -storepasswd 更改密钥库的存储口令
 -keypasswd 更改条目的密钥口令
 // 导入导出:Java领域 与 C领域互通
 -exportcert 导出证书
 -printcert 打印证书内容
 -importcert 导入证书或证书链 
 // CA给证书签名相关
 -certreq 生成证书请求
 -printcertreq 打印证书请求的内容
 -gencert 根据证书请求生成证书
 // 跟其他JKS互通
 -importkeystore 从其他密钥库导入一个或所有条目
 -genseckey 生成密钥
 -importpass 导入口令
 -printcrl 打印 CRL 文件的内容
使用 "keytool -command_name -help" 获取 command_name 的用法

演示操作

图中第4步,分发证书的passport.cer的时候,既可以从1步到第4步,通过CA签发;也可以直接自己导出证书,相当于自签发(只不过没有CA担保)。

秘钥实操

生成秘钥

downgoon站点的passport系统和livecam系统分别创建一个秘钥,并集中保存在downgoon.jks文件中:

keytool -genkey -alias passport -keystore downgoon.jks
keytool -genkey -alias livecam -keystore downgoon.jks

敲回车后,会有交互画面让输入各种信息。比如口令信息:

  • keystore 的口令:ks1234
  • passport 的口令:ppt123
  • livecam 的口令:lcm123

注意:

  • keytool -genkey等效于keytool -genkeypair

当然,也可以以非交互方式创建秘钥:

keytool -genkeypair -alias product -keypass pdt123 -keystore downgoon.jks -storepass ks1234 -validity 180 -dname "cn=downgoon Lee, ou=product, o=downgoon, c=CN"
  • 指定秘钥名字与口令: -alias product -keypass pdt123
  • 指定库文件与口令:-keystore downgoon.jks -storepass ks1234
  • 指定秘钥有效天数:-validity 180

帮助信息:

$ keytool -genkeypair --help
keytool -genkeypair [OPTION]...
生成密钥对
选项:
 -alias <alias> 要处理的条目的别名
 -keyalg <keyalg> 密钥算法名称
 -keysize <keysize> 密钥位大小
 -sigalg <sigalg> 签名算法名称
 -destalias <destalias> 目标别名
 -dname <dname> 唯一判别名
 -startdate <startdate> 证书有效期开始日期/时间
 -ext <value> X.509 扩展
 -validity <valDays> 有效天数
 -keypass <arg> 密钥口令
 -keystore <keystore> 密钥库名称
 -storepass <arg> 密钥库口令
 -storetype <storetype> 密钥库类型
 -providername <providername> 提供方名称
 -providerclass <providerclass> 提供方类名
 -providerarg <arg> 提供方参数
 -providerpath <pathlist> 提供方类路径
 -v 详细输出
 -protected 通过受保护的机制的口令

显示列表

$ keytool -list -keystore downgoon.jks -storepass ks1234
product, 2017年10月17日, PrivateKeyEntry,
证书指纹 (SHA1): 13:FD:C2:D3:0B:34:9E:3F:B8:CA:8E:90:AF:D5:40:E2:82:F7:7D:A2
passport, 2017年10月17日, PrivateKeyEntry,
证书指纹 (SHA1): 0F:D3:E9:27:49:89:F7:BA:99:34:A3:DC:0F:09:C8:B2:73:EE:FC:3C
livecam, 2017年10月17日, PrivateKeyEntry,
证书指纹 (SHA1): 2A:8C:CD:1C:A2:54:79:1F:C4:76:38:60:B8:2D:7B:28:8F:52:60:36

如果要详细显示,请用-v选项:

$ keytool -list -keystore downgoon.jks -storepass ks1234 -v

证书实操

导出证书

秘钥对既包含公钥,也包含私钥。但是安全通信过程中,需要把公钥部分,发布给合作方。于是我们需要从秘钥对中导出公钥。 举个例子,从downgoon.jks秘钥库中,导出passport的公钥,并输出到文件passport.cer:

$ keytool -exportcert -alias passport -keystore downgoon.jks -file passport.cer
输入库口令:ks1234

查看证书

导出后,我们不放心,想肉眼查看一下,怎么打开passport.cer呢?

$ keytool -printcert -file passport.cer
  • 适合人类看的格式

输出信息:

$ keytool -printcert -file passport.cer
所有者: CN=Lee, OU=downgoon.com, O=downgoon, L=bj, ST=bj, C=CN
发布者: CN=Lee, OU=downgoon.com, O=downgoon, L=bj, ST=bj, C=CN
序列号: 7f41b1cd
有效期开始日期: Tue Oct 17 09:47:18 CST 2017, 截止日期: Mon Jan 15 09:47:18 CST 2018
证书指纹:
	 MD5: B4:6F:E6:52:BC:DF:E3:2E:CE:5E:6D:5C:AC:5D:80:E9
	 SHA1: 0F:D3:E9:27:49:89:F7:BA:99:34:A3:DC:0F:09:C8:B2:73:EE:FC:3C
	 SHA256: 68:BB:89:97:71:AD:09:76:0C:10:13:52:2A:25:47:66:30:2B:06:69:F2:BD:22:27:18:A8:D6:63:61:BF:29:26
	 签名算法名称: SHA1withDSA
	 版本: 3
扩展:
1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 2C 48 D5 1F F2 DE 25 80 25 3E DB 4F F2 DF D8 48 ,H....%.%>.O...H
0010: 80 23 64 AF .#d.
]
]
  • 适合机器看的格式:RFC格式
$ keytool -printcert -file passport.cer -rfc
-----BEGIN CERTIFICATE-----
MIIDGzCCAtigAwIBAgIEf0GxzTALBgcqhkjOOAQDBQAwXzELMAkGA1UEBhMCQ04xCzAJBgNVBAgT
AmJqMQswCQYDVQQHEwJiajERMA8GA1UEChMIZG93bmdvb24xFTATBgNVBAsTDGRvd25nb29uLmNv
bTEMMAoGA1UEAxMDTGVlMB4XDTE3MTAxNzAxNDcxOFoXDTE4MDExNTAxNDcxOFowXzELMAkGA1UE
BhMCQ04xCzAJBgNVBAgTAmJqMQswCQYDVQQHEwJiajERMA8GA1UEChMIZG93bmdvb24xFTATBgNV
BAsTDGRvd25nb29uLmNvbTEMMAoGA1UEAxMDTGVlMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/
U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00
b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith
1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmU
r7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOu
HiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQA
AoGAKKIKfCZ+AAcSco9MKnnorSc704+l79jYLF3eqgK2H4YkQPlfZMD4EPPlNMexXvwL/Gew6jGD
Kg1+EaHjTmsZuzC0gyBYVsh9WkqSL5cN9GMdfslCqH7ufrqmGPOgHZmBXTWqzIE1teJS+SwNBXeR
PHfZxFY+Ud9sa9VeF/9AM8OjITAfMB0GA1UdDgQWBBQsSNUf8t4lgCU+20/y39hIgCNkrzALBgcq
hkjOOAQDBQADMAAwLQIVAIn4KDCmnqwiKiVzc/3Yh6vo+YwxAhRy+mMJN6m+/5CfRlRmcgnQwxB6
mg==
-----END CERTIFICATE-----

导入证书

我们导出的证书,需要发给合作商,合作商则需要把我们的证书导入(这样合作商只知道我们的公钥,并不知道我们的私钥)。 加入我们的合作商是百度,那么我们模拟百度的行为,把passport.cer证书导入到baidu.jks文件中,并起名叫downgoon_passport:

$ keytool -import -alias downgoon_passport -file passport.cer -keystore baidu.jks
输入库口令:bd1234
提示是否信任此证书?:yes

导入的时候,为什么会提示"是否信任此证书呢"? 因为这个证书没有被CA签名。 另外我们会发现,导入.cer文件的时候,并不需要key级口令。因为公钥本来就是公开的呀,没必要口令保护。

导入完成后,作为合作伙伴的百度,也可以查看一下:

$ keytool -list -keystore baidu.jks
输入密钥库口令: bd1234
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 1 个条目
downgoon_passport, 2017年10月17日, trustedCertEntry, (显示受信任的证书实体)
证书指纹 (SHA1): 0F:D3:E9:27:49:89:F7:BA:99:34:A3:DC:0F:09:C8:B2:73:EE:FC:3C

如果非交互的导入,可以:

keytool -import -alias downgoon_passport -file passport.cer -keystore baidu.jks -storepass bd1234 -v -trustcacerts -noprompt

注意两点:(1)-trustcacerts强制信任该证书,无论是否CA签名;(2)-noprompt不提示。

CA签名实操

前面说道,我们的passport.cer是没有被CA签名的。那么怎么让CA签名呢?很简单,你得先生成一个证书签名请求文件,拿着它和钱,给CA机构去签名,CA会返回我们一个 带有CA盖章 的证书文件。

为了不收钱,我们可以自己做CA。

模拟一个CA

模拟的CA叫myca

创建CA秘钥

keytool -genkeypair -alias rootkey -keypass rky123 -keystore myca.jks -storepass mc1234 -validity 180 -dname "cn=myca, ou=根秘钥, o=myca认证中心, c=CN"

生成证书签名请求

作为downgoon公司,不需要直接导出公钥了,而是需要导出证书的签名请求文件,以便拿去给CA机构签名:

  • 生成签名请求文件:passport.csr
keytool -certreq -alias passport -keypass ppt123 -keystore downgoon.jks -storepass ks1234 -file passport.csr
  • 对比直接导出证书
$ keytool -exportcert -alias passport -keystore downgoon.jks -storepass ks1234 -file passport.cer
  • 查看签名请求文件:passport.csr
$ keytool -printcertreq -file passport.csr
PKCS #10 证书请求 (版本 1.0)
主题: CN=Lee, OU=downgoon.com, O=downgoon, L=bj, ST=bj, C=CN
公共密钥: X.509 格式 DSA 密钥 (默认类型是DSA,不是RSA)
扩展请求:
1: ObjectId: 2.5.29.14 Criticality=false (没有被签名)
SubjectKeyIdentifier [
KeyIdentifier [
0000: 2C 48 D5 1F F2 DE 25 80 25 3E DB 4F F2 DF D8 48 ,H....%.%>.O...H
0010: 80 23 64 AF .#d.
]
]

CA签发证书

CA签发就是把downgoon公司提交过来的passport.csr,盖章后,输出passport.cer文件。下面我们扮演CA公司的操作员:

$ keytool -gencert -alias rootkey -keypass rky123 -keystore myca.jks -storepass mc1234 -infile passport.csr -outfile passport.cer

其中:

  • keytool -gencert 表示生成证书指令,是依据证书签名请求passport.csr文件来生成。
  • -infile passport.csr 指定证书签名请求文件是passport.csr
  • -outfile passport.cer 指定输出被CA签名的证书文件。

分发给申请方

作为申请方,我们可以查看下这个证书,到底有没有CA签名,我们执行查看证书指令:

$ keytool -printcert -file passport.cer

显示的内容:

所有者: CN=Lee, OU=downgoon.com, O=downgoon, L=bj, ST=bj, C=CN
发布者: CN=myca, OU=根秘钥, O=myca认证中心, C=CN (提示了证书签发机构)
序列号: 72010deb
有效期开始日期: Tue Oct 17 11:06:55 CST 2017, 截止日期: Mon Jan 15 11:06:55 CST 2018
证书指纹:
	 MD5: B6:38:AE:09:4E:07:00:06:8E:6D:CB:48:F3:00:7A:52
	 SHA1: D9:44:25:27:93:B7:33:A2:B1:B3:BD:D9:53:83:0E:85:31:C2:D9:85
	 SHA256: 17:19:7E:00:2A:66:0F:E2:EE:B1:DE:A0:11:10:F5:C2:41:66:E5:9A:52:37:BF:10:21:62:6B:2B:8D:73:94:13
	 签名算法名称: SHA1withDSA
	 版本: 3
 扩展:
 #1: ObjectId: 2.5.29.35 Criticality=false
 AuthorityKeyIdentifier [ (证书签发机构的公钥索引)
 KeyIdentifier [
 0000: 7D 26 51 F2 2C C7 88 F7 CC 70 3D DF 26 D7 93 72 .&Q.,....p=.&..r
 0010: 84 0D EC 0B ....
 ]
 ]
 2: ObjectId: 2.5.29.14 Criticality=false
 SubjectKeyIdentifier [
 KeyIdentifier [
 0000: 2C 48 D5 1F F2 DE 25 80 25 3E DB 4F F2 DF D8 48 ,H....%.%>.O...H
 0010: 80 23 64 AF .#d.
 ]
 ]

两个重要信息:

  • 发布者: CN=myca, OU=根秘钥, O=myca认证中心, C=CN
  • AuthorityKeyIdentifier 表示证书签发机构的公钥索引,证书接收方可以依据这个信息,去CA公司做鉴定。

我们可以对比,在第一章节,我们直接导出的,没有被CA签名的证书:

$ keytool -printcert -file passport.cer.unsign
所有者: CN=Lee, OU=downgoon.com, O=downgoon, L=bj, ST=bj, C=CN
发布者: CN=Lee, OU=downgoon.com, O=downgoon, L=bj, ST=bj, C=CN
序列号: 7f41b1cd
有效期开始日期: Tue Oct 17 09:47:18 CST 2017, 截止日期: Mon Jan 15 09:47:18 CST 2018
证书指纹:
	 MD5: B4:6F:E6:52:BC:DF:E3:2E:CE:5E:6D:5C:AC:5D:80:E9
	 SHA1: 0F:D3:E9:27:49:89:F7:BA:99:34:A3:DC:0F:09:C8:B2:73:EE:FC:3C
	 SHA256: 68:BB:89:97:71:AD:09:76:0C:10:13:52:2A:25:47:66:30:2B:06:69:F2:BD:22:27:18:A8:D6:63:61:BF:29:26
	 签名算法名称: SHA1withDSA
	 版本: 3
扩展:
1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 2C 48 D5 1F F2 DE 25 80 25 3E DB 4F F2 DF D8 48 ,H....%.%>.O...H
0010: 80 23 64 AF .#d.
]
]

相比之下,就是缺少刚才的两个东西。

生产注意事项

系统层面证书管理工具

操作系统层面,一般都有一个集中管理证书的:比如window以IE为入口;mac以safari为入口。在Mac下,以Mac工具打开passport.cer证书文件:

这个功能就好比:keytool -printcert

为什么有了系统级的,Java还要搞自己的呢?因为Java定位是跨平台的。自然不能依赖某个操作系统的证书管理。

为什么这个证书虽然有CA签发,但是依然会警告呢?因为CA本身就不被系统证书管理工具信任。免费的CA,且被大多数系统信任的有:letsencryt

更换RSA算法

默认生成的是DSA算法,可以选RSA算法。

增加选项参数:-keyalg RSA -keysize 1024,秘钥长度可以调整为:512或2048等。

参考资料

http://blog.csdn.net/fengwind1/article/details/52191520

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /