目录

  1. 简说RSA

  2. 服务器的初始密钥对和认证请求

  3. 证书认证机构CA

  4. 服务器安装CA签名证书

  5. 客户机

  6. 小结

从样板戏《红灯记》到好莱坞谍战大片《风语者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)

证明如下:

  1. 因为 e * d ≡ 1 (mod (p1-1)*(p2-1)),所以存在整数k使 ed = k * (p1-1) * (p2-1) + 1

  2. 因此 me * d  ≡ m * mk*(p1-1)*(p2-1)  (mod N)

  3. 因p1和p2为质数,由费马小定理,mk*(p1-1)*(p2-1) ≡ 1 (mod p1),mk*(p1-1)*(p2-1) ≡ 1 (mod p2)

  4. 所以 mk*(p1-1)*(p2-1) ≡ 1 (mod lcm[p1,p2]),即 mk*(p1-1)*(p2-1) ≡ 1 (mod N)

  5. 根据同余乘法性质,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握手过程:

  1. 客户机通过网络发送请求安全会话的消息(通常请求是HTTPS协议的形式)。服务器通过发送其X.509证书(包含公钥)进行响应。

  2. 客户机验证服务器证书的有效性,并检验该证书是否由可信任的证书认证机构(CA - certification authority)所签发。

  3. 当证书有效,客户机生成一次性的密钥,并用服务器的公钥对该密钥进行加密。然后,客户机把加密的会话密钥发送给服务器。

  4. 服务器用其私钥对其次进行解密,然后得到本次通讯的会话密钥。

  5. 客户机和服务器用其约定的会话密钥开始数据通信,直到一次会话结束。

由于编写密钥代码的复杂性,许多网站使用开源免费软件。OpenSSL就是这样的一套原码公开的C语言函数库,它最初由Eric和Tim在入职RSA公司前开发,其丰富的在线使用手册可以通过下列命令得到:

$ openssl -helpStandard 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
x509Message Digest commands
md2               md4               md5               rmd160
sha               sha1Cipher 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: SUNYour keystore contains 1 entryAlias 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:DFSHA1: 91:90:23:55:D0:......:F6:BB:5B:21:15:59SHA256: DE:8A:82:8D:56:......:F7:54:EE:9A:2E:7B:97Signature algorithm name: SHA256withRSAVersion: 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:DFSHA1: 91:90:23:55:D0:......:F6:BB:5B:21:15:59SHA256: DE:8A:82:8D:56:......:F7:54:EE:9A:2E:7B:97Signature algorithm name: SHA256withRSAVersion: 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,95C784432BD4A3B3M8tg+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.key0:d=0  hl=4 l=1188 cons: SEQUENCE4:d=1  hl=2 l=   1 prim:  INTEGER  :007:d=1  hl=4 l= 257 prim:  INTEGER  :89D3121B945ABDAD93AF4825DF6....268:d=1  hl=2 l=   3 prim:  INTEGER  :010001273: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.key0:d=0  hl=4 l=1214 cons: SEQUENCE4:d=1  hl=2 l=   1 prim:  INTEGER  :007:d=1  hl=2 l=  13 cons:  SEQUENCE9:d=2  hl=2 l=   9 prim:   OBJECT   :rsaEncryption20:d=2  hl=2 l=   0 prim:   NULL22: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 220:d=0  hl=4 l=1188 cons: SEQUENCE4:d=1  hl=2 l=   1 prim:  INTEGER  :007:d=1  hl=4 l= 257 prim:  INTEGER  :89D3121B945ABDAD93AF4825DF6....268:d=1  hl=2 l=   3 prim:  INTEGER  :010001273: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: sha256WithRSAEncryptionIssuer: CN=www.mysite.comValidityNot Before: Sep 28 04:59:44 20xx GMTNot After : Dec 27 04:59:44 20xx GMTSubject: CN=www.mysite.comSubject Public Key Info:Public Key Algorithm: rsaEncryptionRSA 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.comX509v3 Subject Key Identifier:07:40:44:3B:8F:2A:5E:88:31:79:AC:AB:89:EF:8B:3C:28:31:99:9DSignature Algorithm: sha256WithRSAEncryption02: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 DER0:d=0  hl=4 l= 748 cons: SEQUENCE4:d=1  hl=4 l= 468 cons:  SEQUENCE8:d=2  hl=2 l=   3 cons:   cont [ 0 ]10:d=3  hl=2 l=   1 prim:    INTEGER      :0213:d=2  hl=2 l=   4 prim:   INTEGER       :4D52195C19:d=2  hl=2 l=  13 cons:   SEQUENCE21:d=3  hl=2 l=   9 prim:    OBJECT       :sha256WithRSAEncryption32:d=3  hl=2 l=   0 prim:    NULL34:d=2  hl=2 l=  25 cons:   SEQUENCE36:d=3  hl=2 l=  23 cons:    SET38:d=4  hl=2 l=  21 cons:     SEQUENCE40:d=5  hl=2 l=   3 prim:      OBJECT     :commonName45:d=5  hl=2 l=  14 prim:      PRINTABLESTRING   :www.mysite.com61:d=2  hl=2 l=  30 cons:   SEQUENCE63:d=3  hl=2 l=  13 prim:    UTCTIME      :150929045944Z78:d=3  hl=2 l=  13 prim:    UTCTIME      :151228045944Z93:d=2  hl=2 l=  25 cons:   SEQUENCE95:d=3  hl=2 l=  23 cons:    SET97:d=4  hl=2 l=  21 cons:     SEQUENCE99:d=5  hl=2 l=   3 prim:      OBJECT     :commonName104:d=5  hl=2 l=  14 prim:      PRINTABLESTRING   :www.mysite.com120:d=2  hl=4 l= 290 cons:   SEQUENCE124:d=3  hl=2 l=  13 cons:    SEQUENCE126:d=4  hl=2 l=   9 prim:     OBJECT      :rsaEncryption137:d=4  hl=2 l=   0 prim:     NULL139:d=3  hl=4 l= 271 prim:    BIT STRING414:d=2  hl=2 l=  60 cons:   cont [ 3 ]416:d=3  hl=2 l=  58 cons:    SEQUENCE418:d=4  hl=2 l=  25 cons:     SEQUENCE420:d=5  hl=2 l=   3 prim:      OBJECT      :X509v3 Subject Alternative Name425:d=5  hl=2 l=  18 prim:      OCTET STRING [HEX DUMP]:3010820E666F....445:d=4  hl=2 l=  29 cons:     SEQUENCE447:d=5  hl=2 l=   3 prim:      OBJECT      :X509v3 Subject Key Identifier452:d=5  hl=2 l=  22 prim:      OCTET STRING [HEX DUMP]:04140740443B....476:d=1  hl=2 l=  13 cons:  SEQUENCE478:d=2  hl=2 l=   9 prim:   OBJECT         :sha256WithRSAEncryption489:d=2  hl=2 l=   0 prim:   NULL491: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.key0:d=0  hl=4 l= 290 cons: SEQUENCE4:d=1  hl=2 l=  13 cons: SEQUENCE6:d=2  hl=2 l=   9 prim: OBJECT    :rsaEncryption17:d=2  hl=2 l=   0 prim: NULL19:d=1  hl=4 l= 271 prim: BIT STRING$ openssl asn1parse -in public.key -strparse 190:d=0  hl=4 l= 266 cons: SEQUENCE4: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.comSubject Public Key Info:Public Key Algorithm: rsaEncryptionRSA 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.comX509v3 Subject Key Identifier:07:40:44:3B:8F:2A:5E:88:31:79:AC:AB:89:EF:8B:3C:28:31:99:9DSignature Algorithm: sha256WithRSAEncryption26: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.csr0:d=0  hl=4 l= 681 cons: SEQUENCE4:d=1  hl=4 l= 401 cons:  SEQUENCE8:d=2  hl=2 l=   1 prim:   INTEGER            :0011:d=2  hl=2 l=  25 cons:   SEQUENCE13:d=3  hl=2 l=  23 cons:    SET15:d=4  hl=2 l=  21 cons:     SEQUENCE17:d=5  hl=2 l=   3 prim:      OBJECT          :commonName22:d=5  hl=2 l=  14 prim:      PRINTABLESTRING :www.mysite.com38:d=2  hl=4 l= 290 cons:   SEQUENCE42:d=3  hl=2 l=  13 cons:    SEQUENCE44:d=4  hl=2 l=   9 prim:     OBJECT           :rsaEncryption55:d=4  hl=2 l=   0 prim:     NULL57:d=3  hl=4 l= 271 prim:    BIT STRING332:d=2  hl=2 l=  75 cons:   cont [ 0 ]334:d=3  hl=2 l=  73 cons:    SEQUENCE336:d=4  hl=2 l=   9 prim:     OBJECT           :Extension Request347:d=4  hl=2 l=  60 cons:     SET349:d=5  hl=2 l=  58 cons:      SEQUENCE351:d=6  hl=2 l=  25 cons:       SEQUENCE353:d=7  hl=2 l=   3 prim:        OBJECT        :X509v3 Subject Alternative Name358:d=7  hl=2 l=  18 prim:        OCTET STRING  [HEX DUMP]:3010820E666F6F2E6D79....378:d=6  hl=2 l=  29 cons:       SEQUENCE380:d=7  hl=2 l=   3 prim:        OBJECT        :X509v3 Subject Key Identifier385:d=7  hl=2 l=  22 prim:        OCTET STRING  [HEX DUMP]:04140740443B8F2A5E88....409:d=1  hl=2 l=  13 cons:  SEQUENCE411:d=2  hl=2 l=   9 prim:   OBJECT             :sha256WithRSAEncryption422:d=2  hl=2 l=   0 prim:   NULL424:d=1  hl=4 l= 257 prim:  BIT STRING$ openssl asn1parse -i -in www.csr -strparse 570:d=0  hl=4 l= 266 cons: SEQUENCE4: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 <<EOF
[ ca ]
default_ca = ca_root
[ ca_root ]
new_certs_dir = intermediate
serial = root/serial.txt
database = root/database.txt
certificate = root/public.crt
private_key = root/private.key
default_days = 3652
default_crl_days = 30
default_md = md5
policy = policy_any
[ policy_any ]
countryName = supplied
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
EOF$ openssl ca -config root/openssl.cnf -in intermediate/public.csr \-out intermediate/public.crt
Using configuration from root/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'GB'
stateOrProvinceName   :PRINTABLE:'Berkshire'
localityName          :PRINTABLE:'Newbury'
organizationName      :PRINTABLE:'CA'
commonName            :PRINTABLE:'CA Intermediate'
Certificate is to be certified until Sep 30 03:41:14 20xx GMT (3652 days)
Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

有了中级证书,认证机构的中级认证部门就具备了依据服务器的www.csr请求,发送具有认证机构签名的服务器SSL证书的能力了。

$ touch intermediate/database.txt
$ echo 01 > intermediate/serial.txt
$ cat > intermediate/openssl.cnf <<EOF
[ ca ]
default_ca = ca_intermediate
[ ca_intermediate ]
new_certs_dir = .
serial = intermediate/serial.txt
database = intermediate/database.txt
certificate = intermediate/public.crt
private_key = intermediate/private.key
default_days = 365
default_crl_days = 30
default_md = md5
copy_extensions = copy
policy = policy_any
[ policy_any ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
EOF$ openssl ca -config intermediate/openssl.cnf -in www.csr -out www.crt
Using configuration from intermediate/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :PRINTABLE:'www.mysite.com'
Certificate is to be certified until Sep 30 03:47:44 20xx GMT (365 days)
Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

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: md5WithRSAEncryptionIssuer: C=GB, ST=Berkshire, O=CA, CN=CA IntermediateValidityNot Before: Oct  1 03:47:44 20xx GMTNot After : Sep 30 03:47:44 20xx GMTSubject: CN=www.mysite.comSubject Public Key Info:Public Key Algorithm: rsaEncryptionRSA 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.comX509v3 Subject Key Identifier:07:40:44:3B:8F:2A:5E:88:31:79:AC:AB:......Signature Algorithm: md5WithRSAEncryption3b: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.crt0:d=0  hl=4 l= 725 cons: SEQUENCE4:d=1  hl=4 l= 445 cons:  SEQUENCE8:d=2  hl=2 l=   1 prim:   INTEGER      :0111:d=2  hl=2 l=  13 cons:   SEQUENCE13:d=3  hl=2 l=   9 prim:    OBJECT      :md5WithRSAEncryption24:d=3  hl=2 l=   0 prim:    NULL26:d=2  hl=2 l=  72 cons:   SEQUENCE28:d=3  hl=2 l=  11 cons:    SET30:d=4  hl=2 l=   9 cons:     SEQUENCE32:d=5  hl=2 l=   3 prim:      OBJECT    :countryName37:d=5  hl=2 l=   2 prim:      PRINTABLESTRING :GB41:d=3  hl=2 l=  18 cons:    SET43:d=4  hl=2 l=  16 cons:     SEQUENCE45:d=5  hl=2 l=   3 prim:      OBJECT    :stateOrProvinceName50:d=5  hl=2 l=   9 prim:      PRINTABLESTRING :Berkshire61:d=3  hl=2 l=  11 cons:    SET63:d=4  hl=2 l=   9 cons:     SEQUENCE65:d=5  hl=2 l=   3 prim:      OBJECT    :organizationName70:d=5  hl=2 l=   2 prim:      PRINTABLESTRING :CA74:d=3  hl=2 l=  24 cons:    SET76:d=4  hl=2 l=  22 cons:     SEQUENCE78:d=5  hl=2 l=   3 prim:      OBJECT    :commonName83:d=5  hl=2 l=  15 prim:      PRINTABLESTRING :CA Intermediate100:d=2  hl=2 l=  30 cons:   SEQUENCE102:d=3  hl=2 l=  13 prim:    UTCTIME     :151001034744Z117:d=3  hl=2 l=  13 prim:    UTCTIME     :160930034744Z132:d=2  hl=2 l=  25 cons:   SEQUENCE134:d=3  hl=2 l=  23 cons:    SET136:d=4  hl=2 l=  21 cons:     SEQUENCE138:d=5  hl=2 l=   3 prim:      OBJECT    :commonName143:d=5  hl=2 l=  14 prim:      PRINTABLESTRING :www.mysite.com159:d=2  hl=4 l= 290 cons:   SEQUENCE163:d=3  hl=2 l=  13 cons:    SEQUENCE165:d=4  hl=2 l=   9 prim:     OBJECT     :rsaEncryption176:d=4  hl=2 l=   0 prim:     NULL178:d=3  hl=4 l= 271 prim:    BIT STRING453:d=1  hl=2 l=  13 cons:  SEQUENCE455:d=2  hl=2 l=   9 prim:   OBJECT       :md5WithRSAEncryption466:d=2  hl=2 l=   0 prim:   NULL468: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: SHA1withRSAVersion: 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.crtModulus=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: MD5withRSAVersion: 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: MD5withRSAVersion: 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: SHA1withRSAVersion: 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: MD5withRSAVersion: 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: MD5withRSAVersion: 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: SHA1withRSAVersion: 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 AttributeslocalKeyID: 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: <No 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: <No 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: MD5withRSAVersion: 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: MD5withRSAVersion: 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: SHA1withRSAVersion: 1

4.4 应用程序的配置

【JBoss】把下列配置加入$CATALINA_HOME/conf/server.xml

<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector port="8443" minSpareThreads="5" maxSpareThreads="75"enableLookups="true" disableUploadTimeout="true" acceptCount="100"  maxThreads="200"scheme="https" secure="true" SSLEnabled="true"keystoreFile="${user.home}/keystore.jks" keystorePass="mypass"clientAuth="false" sslProtocol="TLS"/>

【Tomcat】把下列配置加入$CATALINA_BASE/conf/server.xml

<-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connectorprotocol="org.apache.coyote.http11.Http11Protocol"port="8443" maxThreads="200"scheme="https" secure="true" SSLEnabled="true"keystoreFile="${user.home}/keystore.jks" keystorePass="mypass"clientAuth="false" sslProtocol="TLS"/>

↑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 <<EOF
[ req ]
distinguished_name = req_dname
prompt = no
[ req_dname ]
C  = CN
ST = My Street
L  = My Locality
O  = My Organization
OU = My Unit
CN = My Common Name
emailAddress = me@email.address
EOF

$ 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

转载于:https://blog.51cto.com/xnuil/1698673

基于RSA的公钥基础体系下安全通信实战相关推荐

  1. 基于RSA公匙--PGP邮件数字签名

    PGP (Pretty Good Privacy) 是一个基于RSA公匙加密体系的邮件加密软件.可以用它对邮件保密以防止非授权者阅读,它还能对邮件加上数字签名从而使收信人可以确认邮件的发送者,并能确信 ...

  2. iOS中使用基于RSA使用公钥加密和公钥解密

    前言 最近在公司项目中被要求使用RSA加密,且要求是全程加解密,期间也是踩了很多的坑,在此做个记录也算给要使用的朋友一点帮助.注意,具体的RSA加密算法内容并不在此文的讨论范围之内.本文更多聚焦于使用 ...

  3. matlab 模态叠加法,基础激励下基于模态叠加法谐响应分析.doc

    基础激励下基于模态叠加法谐响应分析 基础激励下基于模态叠加法谐响应分析 摘要: 针对ANSYS等商业有限元软件无法进行基础激励下基于模态叠加法的谐响应分析的问题,将以绝对响应为变量的动力学方程改写为基 ...

  4. 一个基于RSA算法的Java数字签名例子

    ====================================================== 注:本文源代码点此下载 ================================= ...

  5. 基于密码的数据安全防护体系研究

    隐私计算研习社 摘 要:数据已成为数字经济时代最核心.最具价值的生产要素,为全球经济增长不断注入新动力.新能量.随着数据利用的不断深入,数据规模不断扩大,数据泄露.滥用等风险日益凸显,亟需建设数据安全 ...

  6. 基于Java技术的Web环境下分布式数据库互操作性的实现

                作者:李炽明 莫倩 徐明 1 JDBC工作原理 JDBC(Java Database Connectivity)是1个Sun公司注册了的商标,代表用来执行SQL语句的Java语 ...

  7. 基于RSA和AES混合加密实现的加解密小工具

    基于RSA和AES混合加密实现的加解密小工具 闲来无事,用python的tkinter开发了一个基于RSA和AES混合加密的小小工具.总结一下使用到的知识点. 首先是核心的加解密部分. 采用混合加密的 ...

  8. iOS端基于RSA公钥加密和解密

    前言 最近在公司项目中被要求使用RSA加密,且要求是全程加解密,期间也是踩了很多的坑,在此做个记录也算给要使用的朋友一点帮助.注意,具体的RSA加密算法内容并不在此文的讨论范围之内.本文更多聚焦于使用 ...

  9. 云原生体系下的技海浮沉与理论探索

    作者 | 王银利(芸峥) 1 . 概述 攻技者,短之:理论者,长之:践行者,胜之.可以这么说,一座城市的良心就体现在下水道上,不论这座城市有多少高楼大厦,建设得有多么宏伟,只要是下雨天,雨水就变成了城 ...

最新文章

  1. Winform开发框架中工作流模块的业务表单开发
  2. 如何修改路由器和交换机的密码
  3. python php linux-Linux 中PHP的安装教程
  4. halcon/c++接口基础 之 析构函数和Halcon算子
  5. Java EE 6示例– Galleria
  6. 无载波幅度和相位调制(CAP)与QAM调制的详细解析(可见光通信应用场景),以及CAP matlab程序下载链接
  7. 《Scikit-Learn与TensorFlow机器学习实用指南》第5章 支持向量机
  8. js浏览器回到顶部方法_基于JS实现回到页面顶部的五种写法(从实现到增强)
  9. 经典的Fisher-Yates Shuffle算法
  10. 互联网最强的下载工具:IDM
  11. 三角矩阵的逆矩阵怎么求_「线性代数」求可逆矩阵P,使得相似矩阵对角化
  12. 一种人机友好的视频压缩方案(HMFVC)
  13. autojs通知栏_监听通知栏失败,请教大佬!
  14. TCP协议-TCP服务特点和头部结构
  15. SXT分布式缓存技术公开课的观后感
  16. coreldraw凹槽_Coreldraw教程:打造逼真静物写生
  17. 云南师范大学计算机专硕,云南师范大学考研难吗?一般要什么水平才可以进入?...
  18. Unity Shader - Billboard 广告板/广告牌 - BB树,BB投影
  19. HP小型机的信息的命令集
  20. 计算机开机桌面一直转圈,Win10开机一直转圈圈怎么办?一直转圈进不去系统的解决方法...

热门文章

  1. 【深度学习】Fashion-MNIST数据集简介
  2. 计算机任务管理器设置软件启动,电脑软件开机自动启动,教你一招禁止启动,能够有效提升开机速度...
  3. unity 弹窗提示_【原创】Unity3D 消息提示框
  4. 机器学习06|两万字:决策树 【jupyter代码详解篇】
  5. 打印日志文件并将其上传存到HDFS中
  6. 洛谷P4218 [CTSC2010]珠宝商(后缀自动机+点分治)
  7. orangepi pc GPIO 管脚图
  8. Oracle Spatial 空间分析之缓冲区分析
  9. 各种css文字样式效果——多个行内元素居中,三点,缩进,阴影等
  10. 与rasp的初次心动