目录

从样板戏《》到好莱坞谍战大片《》等,许许多多动人故事都围绕一个密电码展开。那个年代通信密码学里都采用如今称为对称密码的技术,在这种技术中,加密和解密都使用同一个密钥。因此,密钥的保存运输对通信的安全性显得尤为重要。直到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)

证明如下:

  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的网络通信过程在规范的公钥体系(PKI - public key infrastructure)下得到完成,数据的加密解密由安全套接字层(SSL - secure socket layer)或传输层安全(TLS - transport layer security)实现。当客户机需要与某个服务器建立通信连接时,双方发生SSL握手过程:

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

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

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

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

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

由于编写密钥代码的复杂性,许多网站使用开源免费软件。就是这样的一套原码公开的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_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)

参考资料:、、、、。  
作者邮箱:zhang(dot)f(at)hotmail(dot)com