目录
|
从样板戏《红灯记》到好莱坞谍战大片《风语者Windtalkers》等,许许多多动人故事都围绕一个密电码展开。那个年代通信密码学里都采用如今称为对称密码的技术,在这种技术中,加密和解密都使用同一个密钥。因此,密钥的保存运输对通信的安全性显得尤为重要。直到70年代非对称密码技术的出现,情况才真正得到改善。在非对称密码技术中密钥是成对出现的,一个私钥一个公钥。通信方只要妥善保管好私钥而开放公钥,就能保证安全通信。
非对称密码技术的出现,让人们发现了另一个用途:数字签名。它和合同商业文书的纸上签名一样,用于鉴别数字文书真实性的方法。一套数字签名通常定义两种互补的对数字文书的密钥运算,私钥用于签名,而公钥用于验证。
网络是一个开放的世界,服务器可以被不法节点冒名顶替,传输的数据可以被整个通路上的任何一个节点监听。要保证客户机和服务器在网络中通信的安全,客户机首先要检查数字签名以验明服务器正身,然后还要加密要传输的数据,该数据到达服务器后再进行解密。非对称密码技术完满地满足了这两种技术诉求。
↑TOP↑
1. 简说RSA
作为非对称密码技术典范的RSA是MIT的Rivest、Shamir和Adleman在1977年提出,他们是少有的几个能用数学换豪宅豪车的天才。三个人以RSA技术成立了数家公司,最有名的当数RSA Security和VeriSign,两家公司最终分别被EMC和Symantec以21亿和12.8亿美元收购。1983年RSA算法申请了专利,直到2000年9月按专利法失效。由于RSA的广泛应用,发明人被授予2002年度的图灵奖。RSA算法需要少少的数学基础,浓缩如下。
1.1 同余
称a、b对N同余,记为a ≡ b (mod N),当且仅当a、b除以N之后的余数相等。
加法性质:若a1 ≡ b1 (mod N),a2 ≡ b2 (mod N),则(a1 + a2) ≡ (b1 + b2) (mod N)。
乘法性质:若a1 ≡ b1 (mod N),a2 ≡ b2 (mod N),则a1 * a2 ≡ b1 * b2 (mod N)。
模数性质:若a ≡ b (mod N1),a ≡ b (mod N2),则a ≡ b (mod lcm[N1, N2]),其中 lcm[N1, N2]为N1, N2的最小公倍数。
1.2 欧拉函数
在小于等于N的正整数之中,与N构成互质关系(coprime)的整数的个数称为欧拉函数φ(N)。
质数的欧拉函数:显然,如果N是质数,则 φ(N)=N-1 。因为质数N与小于它的每一个数都构成互质关系。
质数乘积的欧拉函数:若p1和p2是质数,则 φ(p1*p2) = φ(p1)*φ(p2) = (p1-1)*(p2-1) 。
1.3 欧拉定理
如果两个正整数a和N互质,则N的欧拉函数 φ(N) 可以让下面的等式成立:
a φ(N) ≡ 1 (mod N)
1.4 费马小定理
欧拉定理中,当N为质数时,任何小于N的整数a,都和N互质。因此作为其特例
若N为质数,则:a N-1 ≡ 1 (mod N)
1.5 RSA原理
㈠ 首先随机选取2个大质数p1和p2,p1≠p2,令N=p1*p2,由此可得φ(N)=(p1-1)*(p2-1);
㈡ 随机取一个小于φ(N),且与φ(N)互质的整数e;
㈢ 计算e对φ(N)的模反元素d,它满足 e * d ≡ 1 (mod φ(N))。记d为 d ≡ e-1 (mod φ(N));
㈣ 把(N,d)妥善保管作为私钥,(N,e)公开作为公钥。对于任何信息m,我们有
m ≡ me * d (mod N)
证明如下:
因为 e * d ≡ 1 (mod (p1-1)*(p2-1)),所以存在整数k使 ed = k * (p1-1) * (p2-1) + 1
因此 me * d ≡ m * mk*(p1-1)*(p2-1) (mod N)
因p1和p2为质数,由费马小定理,mk*(p1-1)*(p2-1) ≡ 1 (mod p1),mk*(p1-1)*(p2-1) ≡ 1 (mod p2)
所以 mk*(p1-1)*(p2-1) ≡ 1 (mod lcm[p1,p2]),即 mk*(p1-1)*(p2-1) ≡ 1 (mod N)
根据同余乘法性质,me * d ≡ m (mod N)
证明毕。
1.6 基于RSA的加密解密方法
发送方加密:以接受方公钥(N,e)对信息m计算 me (mod N)
接受方解密:以接受方私钥(N,d)还原信息m,计算 (me (mod N))d = me * d (mod N) = m
1.7 基于RSA的数字签名方法
发送方签名:以发送方私钥(N,d)对信息m的散列函数h(m),计算 h(m)d (mod N) = h
接受方验证:用发送方公钥(N,e)计算 (hd (mod N))e = he * d (mod N) = h,比较其是否与h(m)值一致
基于RSA的网络通信过程在X.509规范的公钥体系(PKI - public key infrastructure)下得到完成,数据的加密解密由安全套接字层(SSL - secure socket layer)或传输层安全(TLS - transport layer security)实现。当客户机需要与某个服务器建立通信连接时,双方发生SSL握手过程:
客户机通过网络发送请求安全会话的消息(通常请求是HTTPS协议的形式)。服务器通过发送其X.509证书(包含公钥)进行响应。
客户机验证服务器证书的有效性,并检验该证书是否由可信任的证书认证机构(CA - certification authority)所签发。
当证书有效,客户机生成一次性的密钥,并用服务器的公钥对该密钥进行加密。然后,客户机把加密的会话密钥发送给服务器。
服务器用其私钥对其次进行解密,然后得到本次通讯的会话密钥。
客户机和服务器用其约定的会话密钥开始数据通信,直到一次会话结束。
由于编写密钥代码的复杂性,许多网站使用开源免费软件。OpenSSL就是这样的一套原码公开的C语言函数库,它最初由Eric和Tim在入职RSA公司前开发,其丰富的在线使用手册可以通过下列命令得到:
$ openssl -help
Standard commands
asn1parse ca ciphers cms
crl crl2pkcs7 dgst dh
dhparam dsa dsaparam ec
ecparam enc engine errstr
gendh gendsa genpkey genrsa
nseq ocsp passwd pkcs12
pkcs7 pkcs8 pkey pkeyparam
pkeyutl prime rand req
rsa rsautl s_client s_server
s_time sess_id smime speed
spkac ts verify version
x509
Message Digest commands
md2 md4 md5 rmd160
sha sha1
Cipher commands
aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb
aes-256-cbc aes-256-ecb base64 bf
bf-cbc bf-cfb bf-ecb bf-ofb
camellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecb
camellia-256-cbc camellia-256-ecb cast cast-cbc
cast5-cbc cast5-cfb cast5-ecb cast5-ofb
des des-cbc des-cfb des-ecb
des-ede des-ede-cbc des-ede-cfb des-ede-ofb
des-ede3 des-ede3-cbc des-ede3-cfb des-ede3-ofb
des-ofb des3 desx idea
idea-cbc idea-cfb idea-ecb idea-ofb
rc2 rc2-40-cbc rc2-64-cbc rc2-cbc
rc2-cfb rc2-ecb rc2-ofb rc4
rc4-40 seed seed-cbc seed-cfb
seed-ecb seed-ofb zlib
客户机、服务器和证书认证机构是涉足安全通信的三方。围绕证书这个技术关键,下面逐一细说三方通信过程中的协作。
↑TOP↑
2. 服务器的初始密钥对和认证请求
基于Java技术的Web服务器通常以服务导向架构为蓝本,通过HTTPS协议将应用程序功能作为服务发送给客户机。通信传输协议的SSL握手过程中,服务器首先将其X.509证书发送给客户机,然后由客户机依据其存储的根CA证书验证该证书的真实性。Java内部维护一个密钥库(keystore),用以存储私钥及其对应的附有证书链的证书。Java为密钥库设置了一个密码,密钥库中的每一个私钥及其证书又有一个密码来控制存取,keytool是管理密钥库的工具软件。
$ keytool -help
Commands:
-certreq Generates a certificate request
-changealias Changes an entry's alias
-delete Deletes an entry
-exportcert Exports certificate
-genkeypair Generates a key pair
-genseckey Generates a secret key
-gencert Generates certificate from a certificate request
-importcert Imports a certificate or a certificate chain
-importkeystore Imports one or all entries from another keystore
-keypasswd Changes the key password of an entry
-list Lists entries in a keystore
-printcert Prints the content of a certificate
-printcertreq Prints the content of a certificate request
-printcrl Prints the content of a CRL file
-storepasswd Changes the store password of a keystore
2.1 创建初始密钥库
若服务器FQDN是www.mysite.com,它在DNS中又有别名foo.mysite.com,创建JKS格式的初始密钥库可以用如下命令完成。
$ keytool -genkeypair -keystore mystore.jks -storepass mypass -alias www \
-keypass mypass -keyalg rsa -dname "CN=www.mysite.com" -ext "SAN=dns:foo.mysite.com"
$ keytool -list -v -keystore mystore.jks -storepass mypass
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: www
Creation date: Sep 28, 20xx
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=www.mysite.com
Issuer: CN=www.mysite.com
Serial number: 4d52195c
Valid from: Tue Sep 28 17:59:44 GMT 20xx until: Mon Dec 27 17:59:44 GMT 20xx
Certificate fingerprints:
MD5: 00:D2:BE:27:4B:......:7E:EF:82:DF
SHA1: 91:90:23:55:D0:......:F6:BB:5B:21:15:59
SHA256: DE:8A:82:8D:56:......:F7:54:EE:9A:2E:7B:97
Signature algorithm name: SHA256withRSA
Version: 3
Extensions:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: foo.mysite.com
]
#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 07 40 44 3B 8F 2A 5E 88 31 79 AC AB 89 EF 8B 3C .@D;.*^.1y.....<
0010: 28 31 99 9D (1..
]
]
可以看到,生成的密钥库mystore.jks里有一个私钥记录PrivateKeyEntry,记录中含有一个证书链(certificate chain),当然目前证书链里只包含一个证书Certificate[1],它的签名方法是SHA256作为散列函数的RSA加密。也许会惊讶地发现,在PrivateKeyEntry里居然没有对其中私钥的描述,这也许是因为Java私钥不公开的原则。我们可以借助于OpenSSL来一探究竟,发现私钥结构的奥秘。
2.1.1 私钥
前面说过,keytool没有从密钥库中提取私钥的功能。因此要想得到私钥,只能先把JKS格式的密钥库转换成PKCS#12格式,然后利用OpenSSL工具。
$ keytool -importkeystore -srckeystore mystore.jks -srcstorepass mypass -srcalias www \
-srckeypass mypass -destkeystore mystore.p12 -deststorepass mypass \
-destkeypass mypass -deststoretype pkcs12
$ keytool -list -v -keystore mystore.p12 -storepass mypass -storetype pkcs12 -alias www \
-keypass mypass
Alias name: www
Creation date: Sep 28, 20xx
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=www.mysite.com
Issuer: CN=www.mysite.com
Serial number: 4d52195c
Valid from: Tue Sep 28 17:59:44 GMT 20xx until: Mon Dec 27 17:59:44 GMT 20xx
Certificate fingerprints:
MD5: 00:D2:BE:27:4B:......:7E:EF:82:DF
SHA1: 91:90:23:55:D0:......:F6:BB:5B:21:15:59
SHA256: DE:8A:82:8D:56:......:F7:54:EE:9A:2E:7B:97
Signature algorithm name: SHA256withRSA
Version: 3
Extensions:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: foo.mysite.com
]
#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 07 40 44 3B 8F 2A 5E 88 31 79 AC AB 89 EF 8B 3C .@D;.*^.1y.....<
0010: 28 31 99 9D (1..
]
]
从密钥库mystore.p12中我们可以用OpenSSL工具提取出私钥,存入的ASCII文件xxx_private.key按DES标准依据密码进行加密,以保证私钥的保密性。
$ openssl pkcs12 -nocerts -in mystore.p12 -passin pass:mypass -passout pass:mypass \
| awk "/--BEGIN/,/--END/" > xxx_private.key
$ cat xxx_private.key
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,95C784432BD4A3B3
M8tg+Erla1YG6K88u6AQJtCe+0iuvri....
isFo28UueQGTSHGYK4AZrIBU38rdb75....
aKYMz5Yd1AAUqBBQlzSyaImlvdza3cX....
-----END RSA PRIVATE KEY-----
进一步,我们可以删除xxx_private.key文件的密码保护,从而得到一个PKCS#1格式的RSA私钥rsa_private.key,此时私钥以Base64编码形式存储。
$ openssl rsa -in xxx_private.key -passin pass:mypass > rsa_private.key
$ cat rsa_private.key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAidMSG5Rava2Tr0g....
F6pL4KMe9xcJF0r5m1cpSBRrxUcBdwg....
4cGPgFIr6O7VD/qN29UZrJ5kwji82yT....
-----END RSA PRIVATE KEY-----
用OpenSSL工具,可以具体查阅rsa_private.key私钥中的详细内容,它包含若干正整数参数。
$ openssl rsa -text -noout -in rsa_private.key
Private-Key: (2048 bit)
modulus:
00:89:d3:12:1b:94:5a:....
18:f4:b2:64:69:b7:1b:....
8d:b7
publicExponent: 65537 (0x10001)
privateExponent:
1e:cc:68:ee:7a:cf:70:....
3c:95:24:b5:2e:f2:bf:....
e1
prime1:
00:ee:41:c4:5b:95:e2:....
d0:2a:24:3f:81:8a:f3:....
66:a4:b7:b7:af:04
prime2:
00:94:16:9d:e1:04:f3:....
73:5a:9f:a3:73:22:72:....
11:a7:b0:48
exponent1:
00:85:43:d2:01:ec:3f:....
43:4d:1f:03:4a:81:1f:....
ca:57:dd:ce:e7:1c
exponent2:
37:c3:d8:8a:0e:da:27:....
a3:76:b0:0f:40:2e:83:....
7b:72:17:a9:6c
coefficient:
00:c1:4c:9f:3f:e6:86:....
f2:87:e7:b9:dc:59:06:....
ce:f7:71:0b:81:83
可以看到,PKCS#1规范的私钥文件把模数(modulus)、公钥指数(publicExponent)、私钥指数(privateExponent)、两个质数(prime1和prime2)、两个附加指数(exponent1和exponent2)、和一个附加系数(coefficient)封装到私钥结构中。按照RSA理论,模数N和私钥指数d足以构成RSA私钥。然而,规范还增加存储了私钥指数e、两个质数p1和p2、两个附加指数e1和e2、和一个附加系数c,目的是为了加速RSA的计算过程。其中p1、p2、e1、e2、和c满足
e * d ≡ 1 (mod φ(N))
e * e1 ≡ 1 (mod (p1-1))
e * e2 ≡ 1 (mod (p2-1))
p2 * c ≡ 1 (mod p1)
上述参数组将以ASN.1的形式被封装到同一个数据结构中,ASN.1的编码格式BER、CER和DER遵循ITU的X.690标准。OpenSSL里有产生ASN.1序列结构的工具。
$ openssl asn1parse -i -in rsa_private.key
0:d=0 hl=4 l=1188 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=4 l= 257 prim: INTEGER :89D3121B945ABDAD93AF4825DF6....
268:d=1 hl=2 l= 3 prim: INTEGER :010001
273:d=1 hl=4 l= 256 prim: INTEGER :1ECC68EE7ACF70357A9C1FBE3ED....
533:d=1 hl=3 l= 129 prim: INTEGER :EE41C45B95E20E29F83DABDC36E....
665:d=1 hl=3 l= 129 prim: INTEGER :94169DE104F341B4BCE9E5FEC1F....
797:d=1 hl=3 l= 129 prim: INTEGER :8543D201EC3F09EF1DC3D90A0EC....
929:d=1 hl=3 l= 128 prim: INTEGER :37C3D88A0EDA27A90EE6A97468C....
1060:d=1 hl=3 l= 129 prim: INTEGER :C14C9F3FE6865043D8BE903F964....
结构中,第7位开始是模数,第268位公钥指数,第273位私钥指数,第533和665位两个质数,第797和929位两个附加指数,第1060位最后一个附加系数。再进一步,可以用OpenSSL工具在RSA私钥的基础上加上版本号、算法标识等附加信息形成PKCS#8格式私钥文件,它是更一般格式的私钥形式,目的是为了包含RSA和其它一切格式的私钥。
$ openssl pkcs8 -topk8 -nocrypt -in rsa_private.key > private.key
$ cat private.key
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAAS....
SCXfYxj0smRptxsNMcd+VkbQKxTkUb9....
CBUVjg4veHsHXPwQH9z5MUCzz4NRmno....
-----END PRIVATE KEY-----
同样,私钥private.key以ASN.1的形式组织。
$ openssl asn1parse -i -in private.key
0:d=0 hl=4 l=1214 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=2 l= 13 cons: SEQUENCE
9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
20:d=2 hl=2 l= 0 prim: NULL
22:d=1 hl=4 l=1192 prim: OCTET STRING HEX DUMP]:308204A4020100....
可以看到,第7位开始是一个rsaEncryption,其密钥数据始于第22位。因此从第22位开始解析,可以得到和前述rsa_private.key同样的数据结构:
$ openssl asn1parse -i -in private.key -strparse 22
0:d=0 hl=4 l=1188 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=4 l= 257 prim: INTEGER :89D3121B945ABDAD93AF4825DF6....
268:d=1 hl=2 l= 3 prim: INTEGER :010001
273:d=1 hl=4 l= 256 prim: INTEGER :1ECC68EE7ACF70357A9C1FBE3ED....
533:d=1 hl=3 l= 129 prim: INTEGER :EE41C45B95E20E29F83DABDC36E....
665:d=1 hl=3 l= 129 prim: INTEGER :94169DE104F341B4BCE9E5FEC1F....
797:d=1 hl=3 l= 129 prim: INTEGER :8543D201EC3F09EF1DC3D90A0EC....
929:d=1 hl=3 l= 128 prim: INTEGER :37C3D88A0EDA27A90EE6A97468C....
1060:d=1 hl=3 l= 129 prim: INTEGER :C14C9F3FE6865043D8BE903F964....
把private.key转化成DER存储格式后可以看到私钥的二进制表达形式。
$ openssl rsa -in private.key -outform DER | hexdump -C
00000000 30 82 04 a4 02 01 00 02 82 01 01 00 89 d3 12 1b |0...............|
00000010 94 5a bd ad 93 af 48 25 df 63 18 f4 b2 64 69 b7 |.Z....H%.c...di.|
......
00000110 01 02 82 01 00 1e cc 68 ee 7a cf 70 35 7a 9c 1f |.......h.z.p5z..|
00000120 be 3e d6 11 3c 95 24 b5 2e f2 bf 97 11 22 5d 3b |.>..<.$......"];|
......
00000210 89 5b b8 8f e1 02 81 81 00 ee 41 c4 5b 95 e2 0e |.[........A.[...|
00000220 29 f8 3d ab dc 36 e4 d0 2a 24 3f 81 8a f3 bc 01 |).=..6..*$?.....|
......
00000290 66 a4 b7 b7 af 04 28 fd 47 02 81 81 00 94 16 9d |f.....(.G.......|
000002a0 e1 04 f3 41 b4 bc e9 e5 fe c1 fb 73 5a 9f a3 73 |...A.......sZ..s|
......
00000320 00 85 43 d2 01 ec 3f 09 ef 1d c3 d9 0a 0e c6 43 |..C...?........C|
00000330 4d 1f 03 4a 81 1f 3d 8c a4 d8 33 ff 83 6b 51 f8 |M..J..=...3..kQ.|
......
000003a0 67 02 81 80 37 c3 d8 8a 0e da 27 a9 0e e6 a9 74 |g...7.....'....t|
000003b0 68 c9 ee a3 76 b0 0f 40 2e 83 85 82 5c 7a 60 af |h...v..@....\z`.|
......
00000420 6c 1f 42 71 02 81 81 00 c1 4c 9f 3f e6 86 50 43 |l.Bq.....L.?..PC|
00000430 d8 be 90 3f 96 45 f2 87 e7 b9 dc 59 06 e2 34 0e |...?.E.....Y..4.|
......
用OpenSSL命令可以方便地把PKCS#8格式的private.key中的RSA私钥提取出来。
$ openssl pkcs8 -nocrypt -in private.key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAidMSG5Rava2Tr0g....
F6pL4KMe9xcJF0r5m1cpSBRrxUcBdwg....
4cGPgFIr6O7VD/qN29UZrJ5kwji82yT....
-----END RSA PRIVATE KEY-----
$ openssl rsa -text -in private.key | awk "/--BEGIN/,/--END/"
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAidMSG5Rava2Tr0g....
F6pL4KMe9xcJF0r5m1cpSBRrxUcBdwg....
4cGPgFIr6O7VD/qN29UZrJ5kwji82yT....
-----END RSA PRIVATE KEY-----
2.1.2 证书
从JKS格式的密钥库mystore.jks中提取自签名证书相对容易。
$ keytool -exportcert -rfc -alias www -keystore mystore.jks \
-storepass mypass > public.crt
$ cat public.crt
-----BEGIN CERTIFICATE-----
MIIC7DCCAdSgAwIBAgIETVIZXDANBgk....
LmNvbTAeFw0xNTA5MjkwNDU5NDRaFw0....
0X8RPF23N3u116E=
-----END CERTIFICATE-----
也可以从PKCS#12格式的密钥库mystore.p12中提取。
$ openssl pkcs12 -in mystore.p12 -nokeys -passin pass:mypass \
| awk "/--BEGIN/,/--END/" > public.crt
分析证书public.crt的结构和具体内容,可以看到这是一个自签名的证书,由Issuer(www.mysite.com)签发给Subject(www.mysite.com)。证书包含一个rsaEncryption公钥(即模数和公钥指数)、一些扩展部分(extensions)、和sha256WithRSAEncryption算法(即sha256散列函数的RSA加密)得到的数字签名。
$ openssl x509 -text -noout -in public.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1297226076 (0x4d52195c)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=www.mysite.com
Validity
Not Before: Sep 28 04:59:44 20xx GMT
Not After : Dec 27 04:59:44 20xx GMT
Subject: CN=www.mysite.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:89:d3:12:1b:94:5a:bd:ad:93:af:48:25:df:63:
18:f4:b2:64:69:b7:1b:0d:31:......
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:foo.mysite.com
X509v3 Subject Key Identifier:
07:40:44:3B:8F:2A:5E:88:31:79:AC:AB:89:EF:8B:3C:28:31:99:9D
Signature Algorithm: sha256WithRSAEncryption
02:d3:e1:20:71:e8:6d:b1:ec:61:bd:88:a5:04:3e:65:6c:2e:
fb:36:61:28:06:d6:77:e7:......
对证书文件也可以做ASN.1分析:
$ openssl x509 -in public.crt -outform DER|openssl asn1parse -i -inform DER
0:d=0 hl=4 l= 748 cons: SEQUENCE
4:d=1 hl=4 l= 468 cons: SEQUENCE
8:d=2 hl=2 l= 3 cons: cont [ 0 ]
10:d=3 hl=2 l= 1 prim: INTEGER :02
13:d=2 hl=2 l= 4 prim: INTEGER :4D52195C
19:d=2 hl=2 l= 13 cons: SEQUENCE
21:d=3 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
32:d=3 hl=2 l= 0 prim: NULL
34:d=2 hl=2 l= 25 cons: SEQUENCE
36:d=3 hl=2 l= 23 cons: SET
38:d=4 hl=2 l= 21 cons: SEQUENCE
40:d=5 hl=2 l= 3 prim: OBJECT :commonName
45:d=5 hl=2 l= 14 prim: PRINTABLESTRING :www.mysite.com
61:d=2 hl=2 l= 30 cons: SEQUENCE
63:d=3 hl=2 l= 13 prim: UTCTIME :150929045944Z
78:d=3 hl=2 l= 13 prim: UTCTIME :151228045944Z
93:d=2 hl=2 l= 25 cons: SEQUENCE
95:d=3 hl=2 l= 23 cons: SET
97:d=4 hl=2 l= 21 cons: SEQUENCE
99:d=5 hl=2 l= 3 prim: OBJECT :commonName
104:d=5 hl=2 l= 14 prim: PRINTABLESTRING :www.mysite.com
120:d=2 hl=4 l= 290 cons: SEQUENCE
124:d=3 hl=2 l= 13 cons: SEQUENCE
126:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
137:d=4 hl=2 l= 0 prim: NULL
139:d=3 hl=4 l= 271 prim: BIT STRING
414:d=2 hl=2 l= 60 cons: cont [ 3 ]
416:d=3 hl=2 l= 58 cons: SEQUENCE
418:d=4 hl=2 l= 25 cons: SEQUENCE
420:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Alternative Name
425:d=5 hl=2 l= 18 prim: OCTET STRING [HEX DUMP]:3010820E666F....
445:d=4 hl=2 l= 29 cons: SEQUENCE
447:d=5 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
452:d=5 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:04140740443B....
476:d=1 hl=2 l= 13 cons: SEQUENCE
478:d=2 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
489:d=2 hl=2 l= 0 prim: NULL
491:d=1 hl=4 l= 257 prim: BIT STRING
$ openssl x509 -in public.crt -outform DER | hexdump -C
00000000 30 82 02 ec 30 82 01 d4 a0 03 02 01 02 02 04 4d |0...0..........M|
00000010 52 19 5c 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |R.\0...*.H......|
00000020 05 00 30 19 31 17 30 15 06 03 55 04 03 13 0e 77 |..0.1.0...U....w|
00000030 77 77 2e 6d 79 73 69 74 65 2e 63 6f 6d 30 1e 17 |ww.mysite.com0..|
00000040 0d 31 35 30 39 32 39 30 34 35 39 34 34 5a 17 0d |.150929045944Z..|
00000050 31 35 31 32 32 38 30 34 35 39 34 34 5a 30 19 31 |151228045944Z0.1|
00000060 17 30 15 06 03 55 04 03 13 0e 77 77 77 2e 6d 79 |.0...U....www.my|
00000070 73 69 74 65 2e 63 6f 6d 30 82 01 22 30 0d 06 09 |site.com0.."0...|
00000080 2a 86 48 86 f7 0d 01 01 01 05 00 03 82 01 0f 00 |*.H.............|
00000090 30 82 01 0a 02 82 01 01 00 89 d3 12 1b 94 5a bd |0.............Z.|
000000a0 ad 93 af 48 25 df 63 18 f4 b2 64 69 b7 1b 0d 31 |...H%.c...di...1|
......
00000190 de c4 07 3a b4 ce ca 8d b7 02 03 01 00 01 a3 3c |...:...........<|
000001a0 30 3a 30 19 06 03 55 1d 11 04 12 30 10 82 0e 66 |0:0...U....0...f|
000001b0 6f 6f 2e 6d 79 73 69 74 65 2e 63 6f 6d 30 1d 06 |oo.mysite.com0..|
000001c0 03 55 1d 0e 04 16 04 14 07 40 44 3b 8f 2a 5e 88 |.U.......@D;.*^.|
000001d0 31 79 ac ab 89 ef 8b 3c 28 31 99 9d 30 0d 06 09 |1y.....<(1..0...|
000001e0 2a 86 48 86 f7 0d 01 01 0b 05 00 03 82 01 01 00 |*.H.............|
000001f0 02 d3 e1 20 71 e8 6d b1 ec 61 bd 88 a5 04 3e 65 |... q.m..a....>e|
00000200 6c 2e fb 36 61 28 06 d6 77 e7......
2.1.3 公钥
OpenSSL提供从证书中提取出公钥的技术手段。
$ openssl x509 -pubkey -noout -in public.crt > public.key
$ cat public.key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8....
9LJkabcbDTHHflZG0CsU5FG/V/BZF6p....
twIDAQAB
-----END PUBLIC KEY-----
前面已经表述,PKCS#1或PKCS#8格式的私钥文件也包含构建公钥的模数和公钥指数,因此可以从rsa_private.key或private.key中提取信息直接生成RSA公钥文件,以此可以与密钥库中提取出来的公钥进行比较。
$ openssl rsa -pubout -in private.key
用OpenSSL可以查看公钥的具体内容。显而易见,它包含模数和公钥指数,通常公钥指数取为216+1。
$ openssl rsa -text -noout -pubin -in public.key
Modulus (2048 bit):
00:89:d3:12:1b:94:5a:bd:ad:93:af:48:25:df:63:
18:f4:b2:64:69:b7:1b:0d:31:......
Exponent: 65537 (0x10001)
同样可以生成ASN.1格式:
$ openssl asn1parse -in public.key
0:d=0 hl=4 l= 290 cons: SEQUENCE
4:d=1 hl=2 l= 13 cons: SEQUENCE
6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
17:d=2 hl=2 l= 0 prim: NULL
19:d=1 hl=4 l= 271 prim: BIT STRING
$ openssl asn1parse -in public.key -strparse 19
0:d=0 hl=4 l= 266 cons: SEQUENCE
4:d=1 hl=4 l= 257 prim: INTEGER :89D3121B945ABDAD....
265:d=1 hl=2 l= 3 prim: INTEGER :010001
最后,鉴别私钥、公钥和证书文件是否配对,可以检查它们各自的模数。密钥对的私钥及其对应的公钥和证书,模数应该相同。
$ openssl rsa -modulus -noout -in private.key
Modulus=89D3121B945ABDAD....
$ openssl rsa -modulus -noout -pubin -in public.key
Modulus=89D3121B945ABDAD....
$ openssl x509 -modulus -noout -in public.crt
Modulus=89D3121B945ABDAD....
2.2 证书签名请求
初始建立的密钥库,包含一个私钥和一个自签名的证书。下一步需要生成PKCS#10格式的证书签名请求(CSR - certificate signing request),然后把证书签名请求提交认证机构CA,等待该机构依据X.509国际标准对服务器管理者进行验证,合格者签发证书。
$ keytool -certreq -keystore mystore.jks -storepass mypass -alias www -keypass mypass \
-ext "SAN=dns:foo.mysite.com" -file www.csr
$ cat www.csr
-----BEGIN NEW CERTIFICATE REQUEST-----
MIICqTCCAZECAQAwGTEXMB......
A4IBDwAwggEKAoIBAQCJ0x......
NA==
-----END NEW CERTIFICATE REQUEST-----
OpenSSL可以检验、显示证书签名请求的内容。请求和证书格式基本相同,它包含一个rsaEncryption公钥(即模数和公钥指数)、一些扩展部分(extensions)、和sha256WithRSAEncryption算法(即sha256散列函数的RSA加密)产生的数字签名。
$ openssl req -verify -noout -in www.csr
verify OK
$ openssl req -text -noout -in www.csr
Certificate Request:
Data:
Version: 0 (0x0)
Subject: CN=www.mysite.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:89:d3:12:1b:94:5a:bd:ad:93:af:48:25:df:63:
18:f4:b2:64:69:b7:1b:0d:31:......
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:foo.mysite.com
X509v3 Subject Key Identifier:
07:40:44:3B:8F:2A:5E:88:31:79:AC:AB:89:EF:8B:3C:28:31:99:9D
Signature Algorithm: sha256WithRSAEncryption
26:4a:73:9f:3f:f8:91:78:b8:1d:9b:51:ab:63:32:c2:1f:cd:
76:3e:de:42:03:e1:7b:11:......
对证书签名请求做ASN.1分析:
$ openssl asn1parse -i -in www.csr
0:d=0 hl=4 l= 681 cons: SEQUENCE
4:d=1 hl=4 l= 401 cons: SEQUENCE
8:d=2 hl=2 l= 1 prim: INTEGER :00
11:d=2 hl=2 l= 25 cons: SEQUENCE
13:d=3 hl=2 l= 23 cons: SET
15:d=4 hl=2 l= 21 cons: SEQUENCE
17:d=5 hl=2 l= 3 prim: OBJECT :commonName
22:d=5 hl=2 l= 14 prim: PRINTABLESTRING :www.mysite.com
38:d=2 hl=4 l= 290 cons: SEQUENCE
42:d=3 hl=2 l= 13 cons: SEQUENCE
44:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
55:d=4 hl=2 l= 0 prim: NULL
57:d=3 hl=4 l= 271 prim: BIT STRING
332:d=2 hl=2 l= 75 cons: cont [ 0 ]
334:d=3 hl=2 l= 73 cons: SEQUENCE
336:d=4 hl=2 l= 9 prim: OBJECT :Extension Request
347:d=4 hl=2 l= 60 cons: SET
349:d=5 hl=2 l= 58 cons: SEQUENCE
351:d=6 hl=2 l= 25 cons: SEQUENCE
353:d=7 hl=2 l= 3 prim: OBJECT :X509v3 Subject Alternative Name
358:d=7 hl=2 l= 18 prim: OCTET STRING [HEX DUMP]:3010820E666F6F2E6D79....
378:d=6 hl=2 l= 29 cons: SEQUENCE
380:d=7 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier
385:d=7 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:04140740443B8F2A5E88....
409:d=1 hl=2 l= 13 cons: SEQUENCE
411:d=2 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
422:d=2 hl=2 l= 0 prim: NULL
424:d=1 hl=4 l= 257 prim: BIT STRING
$ openssl asn1parse -i -in www.csr -strparse 57
0:d=0 hl=4 l= 266 cons: SEQUENCE
4:d=1 hl=4 l= 257 prim: INTEGER :89D3121B945ABDAD93AF....
265:d=1 hl=2 l= 3 prim: INTEGER :010001
其结果可以和二进制存储文件进行比较。
$ openssl asn1parse -noout -in www.csr -out >(hexdump -C)
00000000 30 82 02 a9 30 82 01 91 02 01 00 30 19 31 17 30 |0...0......0.1.0|
00000010 15 06 03 55 04 03 13 0e 77 77 77 2e 6d 79 73 69 |...U....www.mysi|
00000020 74 65 2e 63 6f 6d 30 82 01 22 30 0d 06 09 2a 86 |te.com0.."0...*.|
00000030 48 86 f7 0d 01 01 01 05 00 03 82 01 0f 00 30 82 |H.............0.|
00000040 01 0a 02 82 01 01 00 89 d3 12 1b 94 5a bd ad 93 |............Z...|
00000050 af 48 25 df 63 18 f4 b2 64 69 b7 1b 0d 31 c7 7e |.H%.c...di...1.~|
......
00000140 07 3a b4 ce ca 8d b7 02 03 01 00 01 a0 4b 30 49 |.:...........K0I|
00000150 06 09 2a 86 48 86 f7 0d 01 09 0e 31 3c 30 3a 30 |..*.H......1<0:0|
00000160 19 06 03 55 1d 11 04 12 30 10 82 0e 66 6f 6f 2e |...U....0...foo.|
00000170 6d 79 73 69 74 65 2e 63 6f 6d 30 1d 06 03 55 1d |mysite.com0...U.|
00000180 0e 04 16 04 14 07 40 44 3b 8f 2a 5e 88 31 79 ac |......@D;.*^.1y.|
00000190 ab 89 ef 8b 3c 28 31 99 9d 30 0d 06 09 2a 86 48 |....<(1..0...*.H|
000001a0 86 f7 0d 01 01 0b 05 00 03 82 01 01 00 26 4a 73 |.............&Js|
000001b0 9f 3f f8 91 78 b8 1d 9b 51 ab 63 32 c2 1f cd 76 |.?..x...Q.c2...v|
......
000002a0 e8 f8 4f 60 23 fc 97 02 c5 d2 6a bf 34 |..O`#.....j.4|
从证书签名请求www.csr可以提取出其间包含的公钥及其模数,与上节产生的私钥公钥的模数进行比较。
$ openssl req -pubkey -noout -in www.csr
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8....
9LJkabcbDTHHflZG0CsU5FG/V/BZF6p....
twIDAQAB
-----END PUBLIC KEY-----
$ openssl req -modulus -noout -in www.csr
Modulus=89D3121B945ABDAD....
↑TOP↑
3. 证书认证机构CA
数字证书认证机构是签发包含公钥的证书的机构,其英文名称是Certificate Authority,经常被缩写为CA。有些简单的SSL证书仅仅需要用该网站域名的邮箱向CA发封邮件就能签发了,数据传输双方以此进行数据安全传输。然而,https加密的目的除了保证客户机信息在传输过程中的安全外,还保障了服务器的身份。对一些正规组织特别是一些金融机构,SSL证书的签发就会变得十分繁琐,这样的网站需要提供大量的文件以证明该网站是可靠的。如果能够证明该网站是可靠的,CA才会给签发证书。目前全球最著名的证书认证机构有:
Symantec--原VeriSign,后被Symantec收购的美国公司。占数字认证市场三分之一的份额
Comodo--英国起家,帮助建立了扩展验证证书(简称EV证书)的新标准。占市场三分之一份额
GlobalSign--日本公司,占数字认证市场10%
GoDaddy--全球最大的域名注册商,业务包括SSL证书。占数字认证市场10%
中国互联网络信息中心--拥有根证书的中国认证机构
香港邮政电子核证--拥有根证书的香港认证机构
澳门邮政eSignTrust--拥有根证书的澳门认证机构
需要补充说明一下EV证书(Extended Validation),这种证书遵循全球统一的严格身份验证标准颁发的SSL证书,是目前业界最高安全级别的SSL证书。它是由Comodo联合VeriSign、GeoTrust、Thawte等证书认证机构,联合主流浏览器开发商微软、Mozilla、Opera等,创立的数字证书和浏览器论坛cabforum.org制定的标准。这种证书在浏览器中以绿色地址栏显示,并且滚动展示该网站真实管理机构和CA信息。如WoSign沃通电子认证服务有限公司的网站https://www.wosign.com/ 。
3.1 根证书
就像可口可乐公司的商业重器可口可乐配方一样,数字证书认证机构的唯一资产就是它所拥有的一个或几个根证书,这些根证书被预置在主流操作系统中,被各个系统所信任。作为演示,我们在这里一个伪“根证书”及其对应的私钥,根证书是以自签名的形式签发的。
$ mkdir root
$ openssl req -newkey rsa:4096 -keyout root/xxx_private.key \
-out root/public.csr
$ openssl pkcs8 -topk8 -nocrypt -in root/xxx_private.key > root/private.key
$ openssl x509 -req -signkey root/private.key -in root/public.csr \
-out root/public.crt
3.2 中级认证
通常,认证机构按照层次结构来组织的,它有一批下属中级认证部门,每个部门又拥有一个或几个中级证书。我们先生成一个中级证书极其CSR来作为演示。
$ mkdir intermediate
$ openssl req -newkey rsa:2048 -keyout intermediate/xxx_private.key \
-out intermediate/public.csr
$ openssl pkcs8 -topk8 -nocrypt -in intermediate/xxx_private.key \
> intermediate/private.key
这些中级证书,均具有根证书的签名。OpenSSL使用根证书完成中级证书的签发。
$ touch root/database.txt
$ echo 01 > root/serial.txt
$ cat > root/openssl.cnf <
有了中级证书,认证机构的中级认证部门就具备了依据服务器的www.csr请求,发送具有认证机构签名的服务器SSL证书的能力了。
$ touch intermediate/database.txt
$ echo 01 > intermediate/serial.txt
$ cat > intermediate/openssl.cnf <
3.3 认证机构发送具有数字签名的数据
证书认证机构应答服务器的是具有数字签名的数据。其原理是,认证机构把要发送的数据用私钥进行签名,然后把数据连同签名一并发送给服务器。
$ echo testing > 1.txt
$ openssl dgst -md5 -sign root/private.key 1.txt > 2.xxx
服务器可以获取的根证书,以此得到认证机构的公钥。
$ openssl x509 -pubkey -noout -in root/public.crt > root/public.key
接受到认证机构的数据及其签名信息后,依据认证机构的公钥对其进行签名验证
$ openssl dgst -md5 -verify root/public.key -signature 2.xxx 1.txt
Verified OK
我们观察www.crt的结构和内容不难发现,生成的证书包含一个公钥和一个签名。服务器收到的包含认证机构md5WithRSAEncryption签名的证书,就表明已经完成了管理者身份的验证。
$ openssl x509 -text -noout -in www.crt
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=GB, ST=Berkshire, O=CA, CN=CA Intermediate
Validity
Not Before: Oct 1 03:47:44 20xx GMT
Not After : Sep 30 03:47:44 20xx GMT
Subject: CN=www.mysite.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:89:d3:12:1b:94:5a:bd:ad:93:af:48:25:df:63:
18:f4:b2:64:69:b7:1b:......
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:foo.mysite.com
X509v3 Subject Key Identifier:
07:40:44:3B:8F:2A:5E:88:31:79:AC:AB:......
Signature Algorithm: md5WithRSAEncryption
3b:63:2c:cc:12:dd:04:f6:48:a9:f8:c2:b9:da:54:d1:a4:d9:
91:f8:b4:c0:25:6a:db:4c:......
$ openssl asn1parse -i -in www.crt
0:d=0 hl=4 l= 725 cons: SEQUENCE
4:d=1 hl=4 l= 445 cons: SEQUENCE
8:d=2 hl=2 l= 1 prim: INTEGER :01
11:d=2 hl=2 l= 13 cons: SEQUENCE
13:d=3 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
24:d=3 hl=2 l= 0 prim: NULL
26:d=2 hl=2 l= 72 cons: SEQUENCE
28:d=3 hl=2 l= 11 cons: SET
30:d=4 hl=2 l= 9 cons: SEQUENCE
32:d=5 hl=2 l= 3 prim: OBJECT :countryName
37:d=5 hl=2 l= 2 prim: PRINTABLESTRING :GB
41:d=3 hl=2 l= 18 cons: SET
43:d=4 hl=2 l= 16 cons: SEQUENCE
45:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
50:d=5 hl=2 l= 9 prim: PRINTABLESTRING :Berkshire
61:d=3 hl=2 l= 11 cons: SET
63:d=4 hl=2 l= 9 cons: SEQUENCE
65:d=5 hl=2 l= 3 prim: OBJECT :organizationName
70:d=5 hl=2 l= 2 prim: PRINTABLESTRING :CA
74:d=3 hl=2 l= 24 cons: SET
76:d=4 hl=2 l= 22 cons: SEQUENCE
78:d=5 hl=2 l= 3 prim: OBJECT :commonName
83:d=5 hl=2 l= 15 prim: PRINTABLESTRING :CA Intermediate
100:d=2 hl=2 l= 30 cons: SEQUENCE
102:d=3 hl=2 l= 13 prim: UTCTIME :151001034744Z
117:d=3 hl=2 l= 13 prim: UTCTIME :160930034744Z
132:d=2 hl=2 l= 25 cons: SEQUENCE
134:d=3 hl=2 l= 23 cons: SET
136:d=4 hl=2 l= 21 cons: SEQUENCE
138:d=5 hl=2 l= 3 prim: OBJECT :commonName
143:d=5 hl=2 l= 14 prim: PRINTABLESTRING :www.mysite.com
159:d=2 hl=4 l= 290 cons: SEQUENCE
163:d=3 hl=2 l= 13 cons: SEQUENCE
165:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
176:d=4 hl=2 l= 0 prim: NULL
178:d=3 hl=4 l= 271 prim: BIT STRING
453:d=1 hl=2 l= 13 cons: SEQUENCE
455:d=2 hl=2 l= 9 prim: OBJECT :md5WithRSAEncryption
466:d=2 hl=2 l= 0 prim: NULL
468:d=1 hl=4 l= 257 prim: BIT STRING
从ASN.1格式里可以看见,从第159位开始的Sequence既是公钥。
$ openssl asn1parse -noout -in www.crt -strparse 159 -out pubkey.der
$ cat pubkey.der | openssl base64
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAidMSG5Rava2Tr0gl32MY
9LJkabcbDTHHflZG0CsU5FG/V/BZF6pL4KMe9xcJF0r5m1cpSBRrxUcBdwgVFY4O
L3h7B1z8EB/c+TFAs8+DUZp6GZ2+4cGPgFIr6O7VD/qN29UZrJ5kwji82yTOABf2
2L+c6dpi7ubu3c7fgnW48lmXwJRJtrtFrWzNhiRYugESfudnS98ykxGJDdIK5OBY
1HRv7Ss5xXiCYUrARchV/ORNaPEuUlDRjKCfa0ea9FC++1y4JbyoTJymueUM78vu
1I1E3gqG3syGOUqygC5kEvFocJ+26rlseJPxgnUGnR/Lbh98De9B0d7EBzq0zsqN
twIDAQAB
把它和用命令提取出来的公钥作个比较,可以看见它们是一致的。
$ openssl x509 -pubkey -noout -in www.crt
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAidMSG5Rava2Tr0gl32MY
9LJkabcbDTHHflZG0CsU5FG/V/BZF6pL4KMe9xcJF0r5m1cpSBRrxUcBdwgVFY4O
L3h7B1z8EB/c+TFAs8+DUZp6GZ2+4cGPgFIr6O7VD/qN29UZrJ5kwji82yTOABf2
2L+c6dpi7ubu3c7fgnW48lmXwJRJtrtFrWzNhiRYugESfudnS98ykxGJDdIK5OBY
1HRv7Ss5xXiCYUrARchV/ORNaPEuUlDRjKCfa0ea9FC++1y4JbyoTJymueUM78vu
1I1E3gqG3syGOUqygC5kEvFocJ+26rlseJPxgnUGnR/Lbh98De9B0d7EBzq0zsqN
twIDAQAB
-----END PUBLIC KEY-----
事实上,RFC5280的4.1.1节说明了证书文件由三个Sequence域构成:第一个域tbsCertificate(即待签名to be signed的缩写),第二个域signatureAlgorithm,和第三个域signatureValue。我们下面把tbsCertificate(第4位开始)和signatureValue(第468位开始)提取出来。
$ openssl asn1parse -noout -in www.crt -strparse 4 -out tbs.der
$ openssl asn1parse -noout -in www.crt -strparse 468 -out sig.der
$ hexdump -C sig.der
00000000 3b 63 2c cc 12 dd 04 f6 48 a9 f8 c2 b9 da 54 d1 |;c,.....H.....T.|
00000010 a4 d9 91 f8 b4 c0 25 6a db 4c ......
签名过程是对tbsCertificate域的散列函数值,再以CA中级证书的私钥值计算RSA值。
$ openssl dgst -md5 -sign intermediate/private.key tbs.der | hexdump -C
00000000 3b 63 2c cc 12 dd 04 f6 48 a9 f8 c2 b9 da 54 d1 |;c,.....H.....T.|
00000010 a4 d9 91 f8 b4 c0 25 6a db 4c ......
3.4 PKCS#7证书链
通常,证书认证机构向服务器管理者颁发PKCS#7格式的证书链:
$ cat www.crt intermediate/public.crt | awk "/--BEGIN/,/--END/" \
> chain.crt
$ openssl crl2pkcs7 -nocrl -certfile chain.crt -out chain.p7b
$ cat chain.p7b
-----BEGIN PKCS7-----
MIIHGAYJKoZIhvcNAQcCoIIH....
1TCCAb0CAQEwDQYJKoZIhvcN....
1HuMu/q/5J+8BVGkNV....
-----END PKCS7-----
OpenSSL可以查阅PKCS#7格式的文件中包含的证书链。
$ openssl pkcs7 -print_certs -in chain.p7b
subject=/CN=www.mysite.com
issuer=/C=GB/ST=Berkshire/O=CA/CN=CA Intermediate
-----BEGIN CERTIFICATE-----
MIIC1TCCAb0CAQEwDQYJKoZIhvcNA....
BAgTCUJlcmtzaGlyZTELMAkGA1UEC....
sCSemwRaoHNK
-----END CERTIFICATE-----
subject=/C=GB/ST=Berkshire/O=CA/CN=CA Intermediate
issuer=/C=GB/ST=Berkshire/L=Newbury/O=CA/CN=CA Root
-----BEGIN CERTIFICATE-----
MIIEDjCCAfYCAQEwDQYJKoZIhvcNA....
BAgTCUJlcmtzaGlyZTEQMA4GA1UEB....
5J+8BVGkNVHmgmZjvakg....
-----END CERTIFICATE-----
↑TOP↑
4. 服务器安装CA签名证书
Java存储国际认可的认证机构的根CA证书在其Truststore中$JAVA_HOME/jre/lib/security/cacerts,默认密码通常为changeit。本文为了模拟,把自己生成的CA根证书加入其中。
# keytool -importcert -trustcacerts -file root/public.crt \
-keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit \
-alias myCA
Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: c5671bc640ecbd38
Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xx
Certificate fingerprints:
MD5: A2:E1:2F:87:D2:37:74:....
SHA1: FA:3A:3B:7E:CB:80:DC:22....
SHA256: 8A:95:7A:DF:8A:C4:77:9D:....
Signature algorithm name: SHA1withRSA
Version: 1
Trust this certificate? [no]: yes
Certificate was added to keystore
$ keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts \
-storepass changeit -alias myCA
myCA, Oct 1, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): FA:3A:3B:7E:CB:80:DC:22:....
4.1 证书链分离证书
服务器得到chain.p7b后,先把证书链分割成若干个单独的证书文件:
$ openssl pkcs7 -print_certs -in chain.p7b | awk \
'BEGIN{i=0} /--BEGIN/{i=-i+1} {if(i>0) print>"ca" i ".crt"} /--END/{i=-i}'
$ cat ca1.crt
-----BEGIN CERTIFICATE-----
MIIC1TCCAb0CAQEwDQYJKoZIhvcNA....
BAgTCUJlcmtzaGlyZTELMAkGA1UEC....
sCSemwRaoHNK
-----END CERTIFICATE-----
$ cat ca2.crt
-----BEGIN CERTIFICATE-----
MIIEDjCCAfYCAQEwDQYJKoZIhvcNA....
BAgTCUJlcmtzaGlyZTEQMA4GA1UEB....
5J+8BVGkNVHmgmZjvakgb....
-----END CERTIFICATE-----
得到的签名证书,一般ca1.crt是和私钥配对的证书,而ca2.crt是CA中级证书。
$ openssl x509 -subject -issuer -noout -in ca1.crt
subject= /CN=www.mysite.com
issuer= /C=GB/ST=Berkshire/O=CA/CN=CA Intermediate
$ openssl x509 -subject -issuer -noout -in ca2.crt
subject= /C=GB/ST=Berkshire/O=CA/CN=CA Intermediate
issuer= /C=GB/ST=Berkshire/L=Newbury/O=CA/CN=CA Root
4.2 证书的验证和安装
签名验证的原理是用CA的中级证书中的公钥来验证tbsCertificate域和signatureValue域。
$ openssl dgst -md5 -verify intermediate/public.key -signature sig.der tbs.der
Verified OK
事实上OpenSSL有更简单的命令检验证书的签名。首先依据CA提供的根证书来检验中级CA证书是否可信任。
$ openssl verify -CAfile root/public.crt ca2.crt
ca2.crt: OK
检验服务器SSL证书ca1.crt需要提供用以签名的中级CA证书和根CA证书。
$ openssl verify -CAfile <(cat ca2.crt root/public.crt) ca1.crt
ca1.crt: OK
或先把根证书和中级证书组成证书链文件ca.crt,然后
$ cat ca2.crt root/public.crt > chain.crt
$ openssl verify -CAfile chain.crt ca1.crt
ca1.crt: OK
检验证书的模数,以确定ca1.crt和自己的CSR请求一致。
$ openssl x509 -modulus -noout -in ca1.crt
Modulus=89D3121B945ABDAD....
确认正确即可以将它们安装到密钥库中,首先安装CA中级证书ca2.crt:
$ keytool -importcert -trustcacerts -file ca2.crt -keystore mystore.jks \
-storepass mypass -alias ca
Certificate was added to keystore
然后再安装ca1.crt,以取代密钥库中原来的自签名证书。
$ keytool -importcert -trustcacerts -file ca1.crt -keystore mystore.jks \
-storepass mypass -alias www -keypass mypass
Certificate reply was installed in keystore
如果需要,可以把修改后的密钥库重新转化成PKCS#12格式:
$ rm mystore.p12
$ keytool -importkeystore -srckeystore mystore.jks -srcstorepass mypass -srcalias www \
-srckeypass mypass -destkeystore mystore.p12 -deststorepass mypass \
-destkeypass mypass -deststoretype pkcs12
最后,再验证一下密钥库就可以看到一个具有三个证书构成的证书链。证书链最后一个是已经存储在Truststore的CA根证书,以此表明整个证书链是可信任的。
$ keytool -list -v -keystore mystore.jks -storepass mypass -alias www -keypass mypass
Alias name: www
Creation date: Oct 1, 20xx
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=www.mysite.com
Issuer: CN=CA Intermediate, O=CA, ST=Berkshire, C=GB
Serial number: 1
Valid from: Thu Oct 01 16:47:44 NZDT 20xx until: Fri Sep 30 16:47:44 NZDT 20xx
Certificate fingerprints:
MD5: C3:CA:A8:10:8D:B9:BF:39:67:....
SHA1: 4B:91:C6:2D:30:D0:2D:E0:98:72:....
SHA256: 15:1F:EA:FE:92:34:A0:EE:C0:CC:....
Signature algorithm name: MD5withRSA
Version: 1
Certificate[2]:
Owner: CN=CA Intermediate, O=CA, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: 1
Valid from: Thu Oct 01 16:41:14 NZDT 20xx until: Tue Sep 30 16:41:14 NZDT 20xx
Certificate fingerprints:
MD5: 09:39:54:D5:02:14:99:A7:D8:....
SHA1: 21:77:D2:20:F4:4B:DA:0D:63:20:....
SHA256: 28:87:4B:4D:8A:A2:B4:0C:6A:A8:....
Signature algorithm name: MD5withRSA
Version: 1
Certificate[3]:
Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: c5671bc640ecbd38
Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xx
Certificate fingerprints:
MD5: A2:E1:2F:87:D2:37:74:CA:25:....
SHA1: FA:3A:3B:7E:CB:80:DC:22:5F:FA:....
SHA256: 8A:95:7A:DF:8A:C4:77:9D:3F:B7:....
Signature algorithm name: SHA1withRSA
Version: 1
$ keytool -list -v -keystore mystore.p12 -storepass mypass -storetype pkcs12 -alias www \
-keypass mypass
Alias name: www
Creation date: Oct 1, 20xx
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=www.mysite.com
Issuer: CN=CA Intermediate, O=CA, ST=Berkshire, C=GB
Serial number: 1
Valid from: Thu Oct 01 16:47:44 NZDT 20xx until: Fri Sep 30 16:47:44 NZDT 20xx
Certificate fingerprints:
MD5: C3:CA:A8:10:8D:B9:BF:39:67:....
SHA1: 4B:91:C6:2D:30:D0:2D:E0:98:72:....
SHA256: 15:1F:EA:FE:92:34:A0:EE:C0:CC:....
Signature algorithm name: MD5withRSA
Version: 1
Certificate[2]:
Owner: CN=CA Intermediate, O=CA, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: 1
Valid from: Thu Oct 01 16:41:14 NZDT 20xx until: Tue Sep 30 16:41:14 NZDT 20xx
Certificate fingerprints:
MD5: 09:39:54:D5:02:14:99:A7:D8:....
SHA1: 21:77:D2:20:F4:4B:DA:0D:63:20:....
SHA256: 28:87:4B:4D:8A:A2:B4:0C:6A:A8:....
Signature algorithm name: MD5withRSA
Version: 1
Certificate[3]:
Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: c5671bc640ecbd38
Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xx
Certificate fingerprints:
MD5: A2:E1:2F:87:D2:37:74:CA:25:....
SHA1: FA:3A:3B:7E:CB:80:DC:22:5F:FA:....
SHA256: 8A:95:7A:DF:8A:C4:77:9D:3F:B7:08:....
Signature algorithm name: SHA1withRSA
Version: 1
4.3 证书直接生成PKCS#12库
也可以直接用私钥和证书生成PKCS#12格式的密钥库。
$ openssl pkcs12 -export -out mystore.pfx -passout pass:mypass \
-inkey private.key -in ca1.crt -certfile chain.crt
$ openssl pkcs12 -in mystore.pfx -nokeys -passin pass:mypass
MAC verified OK
Bag Attributes
localKeyID: 4B 91 C6 2D 30 D0 2D E0 98 72 C3....
subject=/CN=www.mysite.com
issuer=/C=GB/ST=Berkshire/O=CA/CN=CA Intermediate
-----BEGIN CERTIFICATE-----
MIIC1TCCAb0CAQEwDQYJKoZIhvcNA....
BAgTCUJlcmtzaGlyZTELMAkGA1UEC....
sCSemwRaoHNK
-----END CERTIFICATE-----
Bag Attributes:
subject=/C=GB/ST=Berkshire/O=CA/CN=CA Intermediate
issuer=/C=GB/ST=Berkshire/L=Newbury/O=CA/CN=CA Root
-----BEGIN CERTIFICATE-----
MIIEDjCCAfYCAQEwDQYJKoZIhvcNA....
BAgTCUJlcmtzaGlyZTEQMA4GA1UEB....
5J+8BVGkNVHmgmZjvak....
-----END CERTIFICATE-----
Bag Attributes:
subject=/C=GB/ST=Berkshire/L=Newbury/O=CA/CN=CA Root
issuer=/C=GB/ST=Berkshire/L=Newbury/O=CA/CN=CA Root
-----BEGIN CERTIFICATE-----
MIIFIDCCAwgCCQDFZxvGQOy9ODANB....
QjESMBAGA1UECBMJQmVya3NoaXJlM....
w6j6KrpgLdawc+kkfKyacSslVAY=
-----END CERTIFICATE-----
$ keytool -list -v -keystore mystore.pfx -storepass mypass -storetype pkcs12
Keystore type: PKCS12
Keystore provider: SunJSSE
Your keystore contains 1 entry
Alias name: 1
Creation date: Oct 1, 20xx
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=www.mysite.com
Issuer: CN=CA Intermediate, O=CA, ST=Berkshire, C=GB
Serial number: 1
Valid from: Thu Oct 01 16:47:44 NZDT 20xx until: Fri Sep 30 16:47:44 NZDT 20xx
Certificate fingerprints:
MD5: C3:CA:A8:10:8D:B9:BF:....
SHA1: 4B:91:C6:2D:30:D0:2D:E0:....
SHA256: 15:1F:EA:FE:92:34:A0:EE:....
Signature algorithm name: MD5withRSA
Version: 1
Certificate[2]:
Owner: CN=CA Intermediate, O=CA, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: 1
Valid from: Thu Oct 01 16:41:14 NZDT 20xx until: Tue Sep 30 16:41:14 NZDT 20xx
Certificate fingerprints:
MD5: 09:39:54:D5:02:14:99:....
SHA1: 21:77:D2:20:F4:4B:DA:0D:....
SHA256: 28:87:4B:4D:8A:A2:B4:0C:....
Signature algorithm name: MD5withRSA
Version: 1
Certificate[3]:
Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Issuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GB
Serial number: c5671bc640ecbd38
Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xx
Certificate fingerprints:
MD5: A2:E1:2F:87:D2:37:74:....
SHA1: FA:3A:3B:7E:CB:80:DC:22:....
SHA256: 8A:95:7A:DF:8A:C4:77:9D:....
Signature algorithm name: SHA1withRSA
Version: 1
4.4 应用程序的配置
【JBoss】把下列配置加入$CATALINA_HOME/conf/server.xml
<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
【Tomcat】把下列配置加入$CATALINA_BASE/conf/server.xml
<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
↑TOP↑
5. 客户机
客户机如果是Windows,微软提供一个证书实用程序来管理密钥证书文件。
C:\> CertUtil -?
Verbs:
-dump -- Dump configuration information or files
-asn -- Parse ASN.1 file
-decodehex -- Decode hexadecimal-encoded file
-decode -- Decode Base64-encoded file
-encode -- Encode file to Base64
-deny -- Deny pending request
-resubmit -- Resubmit pending request
-setattributes -- Set attributes for pending request
-setextension -- Set extension for pending request
-revoke -- Revoke Certificate
-isvalid -- Display current certificate disposition
-getconfig -- Get default configuration string
-ping -- Ping Active Directory Certificate Services Request interface
-pingadmin -- Ping Active Directory Certificate Services Admin interface
-CAInfo -- Display CA Information
-ca.cert -- Retrieve the CA's certificate
-ca.chain -- Retrieve the CA's certificate chain
-GetCRL -- Get CRL
-CRL -- Publish new CRLs [or delta CRLs only]
-shutdown -- Shutdown Active Directory Certificate Services
-installCert -- Install Certification Authority certificate
-renewCert -- Renew Certification Authority certificate
-schema -- Dump Certificate Schema
-view -- Dump Certificate View
-db -- Dump Raw Database
-deleterow -- Delete server database row
-backup -- Backup Active Directory Certificate Services
-backupDB -- Backup Active Directory Certificate Services database
-backupKey -- Backup Active Directory Certificate Services certificate and private key
-restore -- Restore Active Directory Certificate Services
-restoreDB -- Restore Active Directory Certificate Services database
-restoreKey -- Restore Active Directory Certificate Services certificate and private key
-importPFX -- Import certificate and private key
-dynamicfilelist -- Display dynamic file List
-databaselocations -- Display database locations
-hashfile -- Generate and display cryptographic hash over a file
-store -- Dump certificate store
-addstore -- Add certificate to store
-delstore -- Delete certificate from store
-verifystore -- Verify certificate in store
-repairstore -- Repair key association or update certificate properties or key security descriptor
-viewstore -- Dump certificate store
-viewdelstore -- Delete certificate from store
-dsPublish -- Publish certificate or CRL to Active Directory
-ADTemplate -- Display AD templates
-Template -- Display Enrollment Policy templates
-TemplateCAs -- Display CAs for template
-CATemplates -- Display templates for CA
-enrollmentServerURL -- Display, add or delete enrollment server URLs associated with a CA
-ADCA -- Display AD CAs
-CA -- Display Enrollment Policy CAs
-Policy -- Display Enrollment Policy
-PolicyCache -- Display or delete Enrollment Policy Cache entries
-CredStore -- Display, add or delete Credential Store entries
-InstallDefaultTemplates -- Install default certificate templates
-URLCache -- Display or delete URL cache entries
-pulse -- Pulse autoenrollment events
-MachineInfo -- Display Active Directory machine object information
-DCInfo -- Display domain controller information
-EntInfo -- Display enterprise information
-TCAInfo -- Display CA information
-SCInfo -- Display smart card information
-SCRoots -- Manage smart card root certificates
-verifykeys -- Verify public/private key set
-verify -- Verify certificate, CRL or chain
-syncWithWU -- Sync with Windows Update
-generateSSTFromWU -- Generate SST from Windows Update
-sign -- Re-sign CRL or certificate
-vroot -- Create/delete web virtual roots and file shares
-vocsproot -- Create/delete web virtual roots for OCSP web proxy
-addEnrollmentServer -- Add an Enrollment Server application
-deleteEnrollmentServer -- Delete an Enrollment Server application
-oid -- Display ObjectId or set display name
-error -- Display error code message text
-getreg -- Display registry value
-setreg -- Set registry value
-delreg -- Delete registry value
-ImportKMS -- Import user keys and certificates into server database for key archival
-ImportCert -- Import a certificate file into the database
-GetKey -- Retrieve archived private key recovery blob
-RecoverKey -- Recover archived private key
-MergePFX -- Merge PFX files
-ConvertEPF -- Convert PFX files to EPF file
通常服务器提供给客户机的证书都附有证书链,它是由一系列CA证书发出的证书序列,最终以根CA证书结束。客户机预 先存储了一组可信任的根CA证书,服务器证书链的终结根CA证书若在其列,客户机即可确认该服务器可信任。在Windows查阅PC中存储的根CA证书, 可以在命令行中键入
C:\> certmgr.msc
客户机从服务器管理者取得证书链ca1.crt和ca2.crt,又从证书认证机构取得根CA证书,便可以验证该证书链的真实性。通常,可信任的证书认证机构的根CA证书均在系统安装时就被预植在各类操作系统中。
$ openssl verify -CAfile root/public.crt ca2.crt
ca2.crt: OK
$ cat ca2.crt root/public.crt > chain.crt
$ openssl verify -CAfile chain.crt ca1.crt
ca1.crt: OK
5.1 客户机测试SSL握手
客户机查询服务器的证书、测试能否用根CA证书与服务器成功完成SSL握手,可以执行如下OpenSSL的命令。通常,OpenSSL本身不包含可信任的根证书库。因此检查默认的OpenSSL配置目录,在未安装配置根证书库/etc/pki/tls/cert.pem的客户机测试可能出错。
$ openssl version -d
OPENSSLDIR: "/etc/pki/tls"
$ openssl s_client -connect www.mysite.com:443
CONNECTED(00000003)
depth=1 CN = www.mysite.com
verify error:num=20:unable to get local issuer certificate
verify return:0
---
当用根CA证书进行同样的测试,可以发现测试通过。
$ openssl s_client -CAfile root/public.crt -connect www.mysite.com:443
CONNECTED(00000003)
depth=2 C = GB, O = CA, CN = CA Root
verify return:1
depth=1 C = GB, O = CA, CN = CA Intermediate
verify return:1
depth=0 CN = www.mysite.com
verify return:1
---
也可以首先构建根CA目录,再对该目录用c_rehash命令建立散列目录,进而进行测试。
$ mkdir cacerts
$ cp root/public.crt cacerts/ca-root.pem
$ c_rehash cacerts
Doing cacerts
ca-root.pem => f9c1c685.0
$ openssl s_client -CApath cacerts -connect www.mysite.com:443
CONNECTED(00000003)
depth=2 C = GB, O = CA, CN = CA Root
verify return:1
depth=1 C = GB, O = CA, CN = CA Intermediate
verify return:1
depth=0 CN = www.mysite.com
verify return:1
---
5.2 客户机向服务器发送加密数据
客户机把要发送的数据有私钥进行签名
$ echo testing > 1.txt
$ openssl rsautl -encrypt -inkey ca1.crt -certin -in 1.txt -out 2.xxx
服务器对接受到数据进行解密
$ openssl rsautl -decrypt -inkey private.key -in 2.xxx -out 3.txt
↑TOP↑
6. 小结
CCITT的X.509采纳了RSA公司的PKCS系列建议,规范建立了PKI下的密钥(PKCS#1和PKCS#8)、签名请求(PKCS#10)、证书(PKCS#7)、密钥库(PKCS#12)等各种数字对象。ITU制定了ASN.1标准以规范描述数字对象的抽象语法,其存储的具体格式有BER、CER、DER等标准,其中DER(Distinguished Encoding Rules)被用在X.509数字签名领域。把DER存储格式进行Base64编码,得到的PEM(Privacy-Enhanced Mail)格式也被纳入X.509中而被广泛应用于密钥、签名请求和证书的存储与交换。
6.1 Java密钥库工具
keytool -genkeypair ... | 生成密钥库记录(.jks) $ keytool -genkeypair -keyalg rsa -keystore 密钥库文件 -storepass 库口令 \ -alias 密钥名 -keypass 私钥口令 -dname "CN=网站名" |
keytool -certreq ... | 生成签名请求(.csr) $ keytool -certreq -keystore 密钥库文件 -storepass 库口令 -alias 密钥名 \ -keypass 私钥口令 -file 签名请求文件 |
keytool -importcert ... | 安装证书(.jks) $ keytool -importcert -trustcacerts -keystore 密钥库 -storepass 库口令 \ -alias 密钥名 -keypass 私钥口令 -file 证书文件 |
keytool -importkeystore ... | 密钥库格式转换(.jks -> .pfx) $ keytool -importkeystore -srckeystore 密钥库文件1 -srcstorepass 库口令1 \ -srcalias 密钥名 -srckeypass 私钥口令1 -destkeystore 密钥库文件2 \ -deststorepass 库口令2 -destkeypass 私钥口令2 -deststoretype pkcs12 |
keytool -list ... | 显示密钥库记录(.jks/.pfx) $ keytool -list -v -keystore 密钥库文件 -storepass 库口令 -alias 密钥名 \ -keypass 私钥口令 |
6.2 OpenSSL工具
6.2.1 RSA私钥PKCS#1
openssl genrsa ... openssl rsa ... |
生成RSA密钥(.key) $ openssl genrsa -des -passout pass:口令 -out 加密RSA私钥 2048 显示RSA密钥 $ openssl rsa -text -noout -passin pass:口令 -in 加密RSA私钥 删除口令 $ openssl rsa -passin pass:口令 -in 加密RSA私钥 -out RSA私钥 显示RSA密钥 $ openssl rsa -text -noout -in RSA私钥
$ openssl rsa -pubout -passin pass:口令 -in 加密RSA私钥 -out 公钥 显示公钥 $ openssl rsa -pubin -text -noout -in 公钥 PEM格式转换成DER格式 # openssl rsa -in RSA私钥.pem -outform der -out RSA私钥.der |
openssl asn1parse ... | RSA私钥的ASN.1分析 |
6.2.2 私钥PKCS#8
openssl pkcs8 ... | 提取私钥(.key) $ openssl pkcs8 -topk8 -nocrypt -in RSA私钥 -out 私钥 显示私钥 $ openssl rsa -text -noout -in 私钥 |
openssl asn1parse ... | 私钥的ASN.1分析 |
6.2.3 签名请求PKCS#10
openssl req ... | 生成签名请求(.csr) $ cat >openssl.cnf < $ openssl req -new -md5 -config openssl.cnf -passin pass:口令 \ -key 加密RSA私钥 -out 签名请求 $ openssl req -new -md5 -config openssl.cnf -key 私钥 -out 签名请求 显示签名请求 $ openssl req -text -noout -in 签名请求 |
openssl ca ... | 签名(.crt) |
6.2.4 证书链PKCS#7
openssl crl2pkcs7 ... | 生成X.509证书链(.p7b) |
openssl pkcs7 ... | 处理X.509证书链(.p7b) |
6.2.5 证书X.509
openssl x509 ... | 处理X.509证书文件(.crt) |
6.2.6 密钥库PKCS#12
openssl pkcs12 ... | 构建PKCS#12格式的密钥库(.pfx) |
参考资料:ASN.1、ASN.1/DER、X.509、Keytool、OpenSSL。
作者邮箱:zhang(dot)f(at)hotmail(dot)com