-
Notifications
You must be signed in to change notification settings - Fork 0
Digital Certificate
密码在配置文件中明文存储不安全,于是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不提示。
前面说道,我们的passport.cer是没有被CA签名的。那么怎么让CA签名呢?很简单,你得先生成一个证书签名请求文件,拿着它和钱,给CA机构去签名,CA会返回我们一个 带有CA盖章 的证书文件。
为了不收钱,我们可以自己做CA。
模拟的CA叫myca。
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签发就是把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。
默认生成的是DSA算法,可以选RSA算法。
增加选项参数:-keyalg RSA -keysize 1024,秘钥长度可以调整为:512或2048等。