目录 |
从样板戏《》到好莱坞谍战大片《》等,许许多多动人故事都围绕一个密电码展开。那个年代通信密码学里都采用如今称为对称密码的技术,在这种技术中,加密和解密都使用同一个密钥。因此,密钥的保存运输对通信的安全性显得尤为重要。直到70年代非对称密码技术的出现,情况才真正得到改善。在非对称密码技术中密钥是成对出现的,一个私钥一个公钥。通信方只要妥善保管好私钥而开放公钥,就能保证安全通信。
非对称密码技术的出现,让人们发现了另一个用途:。它和合同商业文书的纸上签名一样,用于鉴别数字文书真实性的方法。一套数字签名通常定义两种互补的对数字文书的密钥运算,私钥用于签名,而公钥用于验证。
网络是一个开放的世界,服务器可以被不法节点冒名顶替,传输的数据可以被整个通路上的任何一个节点监听。要保证客户机和服务器在网络中通信的安全,客户机首先要检查数字签名以验明服务器正身,然后还要加密要传输的数据,该数据到达服务器后再进行解密。非对称密码技术完满地满足了这两种技术诉求。
1. 简说RSA
作为非对称密码技术典范的RSA是MIT的Rivest、Shamir和Adleman在1977年提出,他们是少有的几个能用数学换豪宅豪车的天才。三个人以RSA技术成立了数家公司,最有名的当数和,两家公司最终分别被EMC和Symantec以21亿和12.8亿美元收购。1983年RSA算法申请了专利,直到2000年9月按专利法失效。由于RSA的广泛应用,发明人被授予。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
㈠ 首先随机选取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的网络通信过程在规范的公钥体系(PKI - public key infrastructure)下得到完成,数据的加密解密由安全套接字层(SSL - secure socket layer)或传输层安全(TLS - transport layer security)实现。当客户机需要与某个服务器建立通信连接时,双方发生SSL握手过程:
客户机通过网络发送请求安全会话的消息(通常请求是HTTPS协议的形式)。服务器通过发送其X.509证书(包含公钥)进行响应。
客户机验证服务器证书的有效性,并检验该证书是否由可信任的证书认证机构(CA - certification authority)所签发。
当证书有效,客户机生成一次性的密钥,并用服务器的公钥对该密钥进行加密。然后,客户机把加密的会话密钥发送给服务器。
服务器用其私钥对其次进行解密,然后得到本次通讯的会话密钥。
客户机和服务器用其约定的会话密钥开始数据通信,直到一次会话结束。
由于编写密钥代码的复杂性,许多网站使用开源免费软件。就是这样的一套原码公开的C语言函数库,它最初由在入职RSA公司前开发,其丰富的在线使用手册可以通过下列命令得到:
$ openssl -helpStandard commandsasn1parse ca ciphers cmscrl crl2pkcs7 dgst dhdhparam dsa dsaparam ececparam enc engine errstrgendh gendsa genpkey genrsanseq ocsp passwd pkcs12pkcs7 pkcs8 pkey pkeyparampkeyutl prime rand reqrsa rsautl s_client s_servers_time sess_id smime speedspkac ts verify versionx509Message Digest commandsmd2 md4 md5 rmd160sha sha1Cipher commandsaes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecbaes-256-cbc aes-256-ecb base64 bfbf-cbc bf-cfb bf-ecb bf-ofbcamellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecbcamellia-256-cbc camellia-256-ecb cast cast-cbccast5-cbc cast5-cfb cast5-ecb cast5-ofbdes des-cbc des-cfb des-ecbdes-ede des-ede-cbc des-ede-cfb des-ede-ofbdes-ede3 des-ede3-cbc des-ede3-cfb des-ede3-ofbdes-ofb des3 desx ideaidea-cbc idea-cfb idea-ecb idea-ofbrc2 rc2-40-cbc rc2-64-cbc rc2-cbcrc2-cfb rc2-ecb rc2-ofb rc4rc4-40 seed seed-cbc seed-cfbseed-ecb seed-ofb zlib
客户机、服务器和证书认证机构是涉足安全通信的三方。围绕证书这个技术关键,下面逐一细说三方通信过程中的协作。
2. 服务器的初始密钥对和认证请求
基于Java技术的Web服务器通常以服务导向架构为蓝本,通过HTTPS协议将应用程序功能作为服务发送给客户机。通信传输协议的SSL握手过程中,服务器首先将其X.509证书发送给客户机,然后由客户机依据其存储的根CA证书验证该证书的真实性。Java内部维护一个密钥库(keystore),用以存储私钥及其对应的附有证书链的证书。Java为密钥库设置了一个密码,密钥库中的每一个私钥及其证书又有一个密码来控制存取,keytool是管理密钥库的工具软件。
$ keytool -helpCommands: -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 mypassKeystore type: JKSKeystore provider: SUNYour keystore contains 1 entryAlias name: wwwCreation date: Sep 28, 20xxEntry type: PrivateKeyEntryCertificate chain length: 1Certificate[1]:Owner: CN=www.mysite.comIssuer: CN=www.mysite.comSerial number: 4d52195cValid from: Tue Sep 28 17:59:44 GMT 20xx until: Mon Dec 27 17:59:44 GMT 20xxCertificate 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: 3Extensions:#1: ObjectId: 2.5.29.17 Criticality=falseSubjectAlternativeName [ DNSName: foo.mysite.com]#2: ObjectId: 2.5.29.14 Criticality=falseSubjectKeyIdentifier [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 mypassAlias name: wwwCreation date: Sep 28, 20xxEntry type: PrivateKeyEntryCertificate chain length: 1Certificate[1]:Owner: CN=www.mysite.comIssuer: CN=www.mysite.comSerial number: 4d52195cValid from: Tue Sep 28 17:59:44 GMT 20xx until: Mon Dec 27 17:59:44 GMT 20xxCertificate 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: 3Extensions:#1: ObjectId: 2.5.29.17 Criticality=falseSubjectAlternativeName [ DNSName: foo.mysite.com]#2: ObjectId: 2.5.29.14 Criticality=falseSubjectKeyIdentifier [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按标准依据密码进行加密,以保证私钥的保密性。
$ 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,ENCRYPTEDDEK-Info: DES-EDE3-CBC,95C784432BD4A3B3M8tg+Erla1YG6K88u6AQJtCe+0iuvri....isFo28UueQGTSHGYK4AZrIBU38rdb75....aKYMz5Yd1AAUqBBQlzSyaImlvdza3cX....-----END RSA PRIVATE KEY-----
进一步,我们可以删除xxx_private.key文件的密码保护,从而得到一个格式的RSA私钥rsa_private.key,此时私钥以编码形式存储。
$ 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.keyPrivate-Key: (2048 bit)modulus: 00:89:d3:12:1b:94:5a:.... 18:f4:b2:64:69:b7:1b:.... 8d:b7publicExponent: 65537 (0x10001)privateExponent: 1e:cc:68:ee:7a:cf:70:.... 3c:95:24:b5:2e:f2:bf:.... e1prime1: 00:ee:41:c4:5b:95:e2:.... d0:2a:24:3f:81:8a:f3:.... 66:a4:b7:b7:af:04prime2: 00:94:16:9d:e1:04:f3:.... 73:5a:9f:a3:73:22:72:.... 11:a7:b0:48exponent1: 00:85:43:d2:01:ec:3f:.... 43:4d:1f:03:4a:81:1f:.... ca:57:dd:ce:e7:1cexponent2: 37:c3:d8:8a:0e:da:27:.... a3:76:b0:0f:40:2e:83:.... 7b:72:17:a9:6ccoefficient: 00:c1:4c:9f:3f:e6:86:.... f2:87:e7:b9:dc:59:06:.... ce:f7:71:0b:81:83
可以看到,规范的私钥文件把模数(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的编码格式BER、CER和DER遵循ITU的标准。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私钥的基础上加上版本号、算法标识等附加信息形成格式私钥文件,它是更一般格式的私钥形式,目的是为了包含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以的形式组织。
$ 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 -C00000000 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.crtCertificate: 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 -C00000000 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.keyModulus (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.keyModulus=89D3121B945ABDAD....$ openssl rsa -modulus -noout -pubin -in public.keyModulus=89D3121B945ABDAD....$ openssl x509 -modulus -noout -in public.crtModulus=89D3121B945ABDAD....
2.2 证书签名请求
初始建立的密钥库,包含一个私钥和一个自签名的证书。下一步需要生成格式的证书签名请求(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.csrverify OK$ openssl req -text -noout -in www.csrCertificate 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.csrModulus=89D3121B945ABDAD....
3. 证书认证机构CA
数字证书认证机构是签发包含公钥的证书的机构,其英文名称是Certificate Authority,经常被缩写为CA。有些简单的SSL证书仅仅需要用该网站域名的邮箱向CA发封邮件就能签发了,数据传输双方以此进行数据安全传输。然而,https加密的目的除了保证客户机信息在传输过程中的安全外,还保障了服务器的身份。对一些正规组织特别是一些金融机构,SSL证书的签发就会变得十分繁琐,这样的网站需要提供大量的文件以证明该网站是可靠的。如果能够证明该网站是可靠的,CA才会给签发证书。目前全球最著名的证书认证机构有:
--原VeriSign,后被Symantec收购的美国公司。占数字认证市场三分之一的份额
--英国起家,帮助建立了扩展验证证书(简称EV证书)的新标准。占市场三分之一份额
--日本公司,占数字认证市场10%
--全球最大的域名注册商,业务包括SSL证书。占数字认证市场10%
--拥有根证书的中国认证机构
--拥有根证书的香港认证机构
--拥有根证书的澳门认证机构
需要补充说明一下EV证书(Extended Validation),这种证书遵循全球统一的严格身份验证标准颁发的SSL证书,是目前业界最高安全级别的SSL证书。它是由Comodo联合VeriSign、GeoTrust、Thawte等证书认证机构,联合主流浏览器开发商微软、Mozilla、Opera等,创立的数字证书和浏览器论坛制定的标准。这种证书在浏览器中以绿色地址栏显示,并且滚动展示该网站真实管理机构和CA信息。如WoSign沃通电子认证服务有限公司的网站 。
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.txtVerified OK
我们观察www.crt的结构和内容不难发现,生成的证书包含一个公钥和一个签名。服务器收到的包含认证机构md5WithRSAEncryption签名的证书,就表明已经完成了管理者身份的验证。
$ openssl x509 -text -noout -in www.crtCertificate: 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 base64MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAidMSG5Rava2Tr0gl32MY9LJkabcbDTHHflZG0CsU5FG/V/BZF6pL4KMe9xcJF0r5m1cpSBRrxUcBdwgVFY4OL3h7B1z8EB/c+TFAs8+DUZp6GZ2+4cGPgFIr6O7VD/qN29UZrJ5kwji82yTOABf22L+c6dpi7ubu3c7fgnW48lmXwJRJtrtFrWzNhiRYugESfudnS98ykxGJDdIK5OBY1HRv7Ss5xXiCYUrARchV/ORNaPEuUlDRjKCfa0ea9FC++1y4JbyoTJymueUM78vu1I1E3gqG3syGOUqygC5kEvFocJ+26rlseJPxgnUGnR/Lbh98De9B0d7EBzq0zsqNtwIDAQAB
把它和用命令提取出来的公钥作个比较,可以看见它们是一致的。
$ openssl x509 -pubkey -noout -in www.crt-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAidMSG5Rava2Tr0gl32MY9LJkabcbDTHHflZG0CsU5FG/V/BZF6pL4KMe9xcJF0r5m1cpSBRrxUcBdwgVFY4OL3h7B1z8EB/c+TFAs8+DUZp6GZ2+4cGPgFIr6O7VD/qN29UZrJ5kwji82yTOABf22L+c6dpi7ubu3c7fgnW48lmXwJRJtrtFrWzNhiRYugESfudnS98ykxGJDdIK5OBY1HRv7Ss5xXiCYUrARchV/ORNaPEuUlDRjKCfa0ea9FC++1y4JbyoTJymueUM78vu1I1E3gqG3syGOUqygC5kEvFocJ+26rlseJPxgnUGnR/Lbh98De9B0d7EBzq0zsqNtwIDAQAB-----END PUBLIC KEY-----
事实上,的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.der00000000 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 -C00000000 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证书链
通常,证书认证机构向服务器管理者颁发格式的证书链:
$ 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.p7bsubject=/CN=www.mysite.comissuer=/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 Intermediateissuer=/C=GB/ST=Berkshire/L=Newbury/O=CA/CN=CA Root-----BEGIN CERTIFICATE-----MIIEDjCCAfYCAQEwDQYJKoZIhvcNA....BAgTCUJlcmtzaGlyZTEQMA4GA1UEB....5J+8BVGkNVHmgmZjvakg....-----END CERTIFICATE-----
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 myCAOwner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: c5671bc640ecbd38Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xxCertificate 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: 1Trust this certificate? [no]: yesCertificate was added to keystore$ keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts \ -storepass changeit -alias myCAmyCA, 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.crtsubject= /CN=www.mysite.comissuer= /C=GB/ST=Berkshire/O=CA/CN=CA Intermediate$ openssl x509 -subject -issuer -noout -in ca2.crtsubject= /C=GB/ST=Berkshire/O=CA/CN=CA Intermediateissuer= /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.derVerified OK
事实上OpenSSL有更简单的命令检验证书的签名。首先依据CA提供的根证书来检验中级CA证书是否可信任。
$ openssl verify -CAfile root/public.crt ca2.crtca2.crt: OK
检验服务器SSL证书ca1.crt需要提供用以签名的中级CA证书和根CA证书。
$ openssl verify -CAfile <(cat ca2.crt root/public.crt) ca1.crtca1.crt: OK
或先把根证书和中级证书组成证书链文件ca.crt,然后
$ cat ca2.crt root/public.crt > chain.crt$ openssl verify -CAfile chain.crt ca1.crtca1.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 caCertificate was added to keystore
然后再安装ca1.crt,以取代密钥库中原来的自签名证书。
$ keytool -importcert -trustcacerts -file ca1.crt -keystore mystore.jks \ -storepass mypass -alias www -keypass mypassCertificate 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 mypassAlias name: wwwCreation date: Oct 1, 20xxEntry type: PrivateKeyEntryCertificate chain length: 3Certificate[1]:Owner: CN=www.mysite.comIssuer: CN=CA Intermediate, O=CA, ST=Berkshire, C=GBSerial number: 1Valid from: Thu Oct 01 16:47:44 NZDT 20xx until: Fri Sep 30 16:47:44 NZDT 20xxCertificate 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: 1Certificate[2]:Owner: CN=CA Intermediate, O=CA, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: 1Valid from: Thu Oct 01 16:41:14 NZDT 20xx until: Tue Sep 30 16:41:14 NZDT 20xxCertificate 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: 1Certificate[3]:Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: c5671bc640ecbd38Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xxCertificate 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 mypassAlias name: wwwCreation date: Oct 1, 20xxEntry type: PrivateKeyEntryCertificate chain length: 3Certificate[1]:Owner: CN=www.mysite.comIssuer: CN=CA Intermediate, O=CA, ST=Berkshire, C=GBSerial number: 1Valid from: Thu Oct 01 16:47:44 NZDT 20xx until: Fri Sep 30 16:47:44 NZDT 20xxCertificate 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: 1Certificate[2]:Owner: CN=CA Intermediate, O=CA, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: 1Valid from: Thu Oct 01 16:41:14 NZDT 20xx until: Tue Sep 30 16:41:14 NZDT 20xxCertificate 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: 1Certificate[3]:Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: c5671bc640ecbd38Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xxCertificate 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:mypassMAC verified OKBag Attributes localKeyID: 4B 91 C6 2D 30 D0 2D E0 98 72 C3....subject=/CN=www.mysite.comissuer=/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 Intermediateissuer=/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 Rootissuer=/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 pkcs12Keystore type: PKCS12Keystore provider: SunJSSEYour keystore contains 1 entryAlias name: 1Creation date: Oct 1, 20xxEntry type: PrivateKeyEntryCertificate chain length: 3Certificate[1]:Owner: CN=www.mysite.comIssuer: CN=CA Intermediate, O=CA, ST=Berkshire, C=GBSerial number: 1Valid from: Thu Oct 01 16:47:44 NZDT 20xx until: Fri Sep 30 16:47:44 NZDT 20xxCertificate 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: 1Certificate[2]:Owner: CN=CA Intermediate, O=CA, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: 1Valid from: Thu Oct 01 16:41:14 NZDT 20xx until: Tue Sep 30 16:41:14 NZDT 20xxCertificate 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: 1Certificate[3]:Owner: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBIssuer: CN=CA Root, O=CA, L=Newbury, ST=Berkshire, C=GBSerial number: c5671bc640ecbd38Valid from: Thu Oct 01 16:37:50 NZDT 20xx until: Sat Oct 31 16:37:50 NZDT 20xxCertificate 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 -->
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.crtca2.crt: OK$ cat ca2.crt root/public.crt > chain.crt$ openssl verify -CAfile chain.crt ca1.crtca1.crt: OK
5.1 客户机测试SSL握手
客户机查询服务器的证书、测试能否用根CA证书与服务器成功完成SSL握手,可以执行如下OpenSSL的命令。通常,OpenSSL本身不包含可信任的根证书库。因此检查默认的OpenSSL配置目录,在未安装配置根证书库/etc/pki/tls/cert.pem的客户机测试可能出错。
$ openssl version -dOPENSSLDIR: "/etc/pki/tls"$ openssl s_client -connect www.mysite.com:443CONNECTED(00000003)depth=1 CN = www.mysite.comverify error:num=20:unable to get local issuer certificateverify return:0---
当用根CA证书进行同样的测试,可以发现测试通过。
$ openssl s_client -CAfile root/public.crt -connect www.mysite.com:443CONNECTED(00000003)depth=2 C = GB, O = CA, CN = CA Rootverify return:1depth=1 C = GB, O = CA, CN = CA Intermediateverify return:1depth=0 CN = www.mysite.comverify return:1---
也可以首先构建根CA目录,再对该目录用c_rehash命令建立散列目录,进而进行测试。
$ mkdir cacerts$ cp root/public.crt cacerts/ca-root.pem$ c_rehash cacertsDoing cacertsca-root.pem => f9c1c685.0$ openssl s_client -CApath cacerts -connect www.mysite.com:443CONNECTED(00000003)depth=2 C = GB, O = CA, CN = CA Rootverify return:1depth=1 C = GB, O = CA, CN = CA Intermediateverify return:1depth=0 CN = www.mysite.comverify 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
6. 小结
CCITT的X.509采纳了RSA公司的PKCS系列建议,规范建立了PKI下的密钥(和)、签名请求()、证书()、密钥库()等各种数字对象。ITU制定了以规范描述数字对象的抽象语法,其存储的具体格式有BER、CER、DER等标准,其中(Distinguished Encoding Rules)被用在X.509数字签名领域。把DER存储格式进行Base64编码,得到的(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_dnameprompt = no[ req_dname ]C = CNST = My StreetL = My LocalityO = My OrganizationOU = My UnitCN = My Common NameemailAddress = me@email.addressEOF$ 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) |