OpenSSL Command Line Tool

Table of Contents

1. OpenSSL 命令行工具

openssl 命令行工具的基本格式为:

$ openssl command [ command_opts ] [ command_args ]

它支持 3 类命令,你可以使用下面命令分别列出这 3 类命令:

$ openssl list -commands          # 也可能为 openssl list-standard-commands
asn1parse         ca                ciphers           cms
crl               crl2pkcs7         dgst              dhparam
dsa               dsaparam          ec                ecparam
enc               engine            errstr            gendsa
genpkey           genrsa            help              list
nseq              ocsp              passwd            pkcs12
pkcs7             pkcs8             pkey              pkeyparam
pkeyutl           prime             rand              rehash
req               rsa               rsautl            s_client
s_server          s_time            sess_id           smime
speed             spkac             srp               storeutl
ts                verify            version           x509

$ openssl list -cipher-commands   # 也可能为 openssl list-cipher-commands
aes-128-cbc       aes-128-ecb       aes-192-cbc       aes-192-ecb
aes-256-cbc       aes-256-ecb       aria-128-cbc      aria-128-cfb
aria-128-cfb1     aria-128-cfb8     aria-128-ctr      aria-128-ecb
aria-128-ofb      aria-192-cbc      aria-192-cfb      aria-192-cfb1
aria-192-cfb8     aria-192-ctr      aria-192-ecb      aria-192-ofb
aria-256-cbc      aria-256-cfb      aria-256-cfb1     aria-256-cfb8
aria-256-ctr      aria-256-ecb      aria-256-ofb      base64
bf                bf-cbc            bf-cfb            bf-ecb
bf-ofb            camellia-128-cbc  camellia-128-ecb  camellia-192-cbc
camellia-192-ecb  camellia-256-cbc  camellia-256-ecb  cast
cast-cbc          cast5-cbc         cast5-cfb         cast5-ecb
cast5-ofb         des               des-cbc           des-cfb
des-ecb           des-ede           des-ede-cbc       des-ede-cfb
des-ede-ofb       des-ede3          des-ede3-cbc      des-ede3-cfb
des-ede3-ofb      des-ofb           des3              desx
rc2               rc2-40-cbc        rc2-64-cbc        rc2-cbc
rc2-cfb           rc2-ecb           rc2-ofb           rc4
rc4-40            seed              seed-cbc          seed-cfb
seed-ecb          seed-ofb          sm4-cbc           sm4-cfb
sm4-ctr           sm4-ecb           sm4-ofb

$ openssl list -digest-commands   # 也可能为 openssl list-message-digest-commands
blake2b512        blake2s256        gost              md4
md5               rmd160            sha1              sha224
sha256            sha3-224          sha3-256          sha3-384
sha3-512          sha384            sha512            sha512-224
sha512-256        shake128          shake256          sm3

使用下面命令可列出 openssl 所支持的密码学算法:

$ openssl list -cipher-algorithms      # 也可能为 openssl list-cipher-algorithms
$ openssl list -digest-algorithms      # 也可能为 openssl list-message-digest-algorithms
$ openssl list -public-key-algorithms  # 也可能为 openssl list-public-key-algorithms

参考:
OpenSSL Command-Line HOWTO
OpenSSL Command Line Utilities
man x509
man req
man ca
man pkcs12

2. 加解密操作

openssl 支持使用对称密钥进行使用加解密操作,这些命令以 openssl enc 开头。

2.1. 实例:使用 des 算法加解密文件

可以用 openssl 对文件进行加密,它的使用比 gpg 简单得多。

加密操作:
把文件 file1.txt 用 des 加密算法加密为 file1.txt.enc

$ openssl enc -des -e -in file1.txt -out file1.txt.enc

其中:
enc 表明你打算使用某个算法加密或解密文件;
-des 表明使用 des 算法进行加密(也可以选择其它加密算法);
-e 表明要加密;
-in 要加密的文件名字;
-out 加密后的文件名字。

运行上面命令,会提示输入密码,要记住这个密码以便解密文件。运行完成后生成的 file1.txt.enc 文件是“乱码”。

解密操作:

$ openssl enc -des -d -in file1.txt.enc -out file1.txt

其中:-d 表明要进行解密

运行上面会提示输入口令,输入正确的口令后,就可以得到解密后的文件了。

2.1.1. Tips:用 -pass 选项传入口令

如果要在脚本中自动化,可以使用选项 -pass 的输入口令,如:

$ openssl enc -des -e -in file1.txt -out file1.txt.enc -pass pass:12345
$ openssl enc -des -d -in file1.txt.enc -out file1.txt -pass pass:12345

2.2. 实例:使用非对称密钥算法加解密文件

使用 openssl pkeyutl -encryptopenssl pkeyutl -decrypt 可以使用公钥加密文件,私钥解密文件。不过这种方法有一个局限: 文件不能太大,否则会提示 data too large for key size,所以不是很实用。 为什么有这个限制呢?这是因为使用公钥加密文件时,背后的原理是把文件内容表示为“一个大整数”,而对这个大整数进行加密,解密时再使用私钥还原出这个大整数。由于大整数也就有一定范围的,我们无法把任意文件表示到这个范围之内。

怎么才能加解密任意大小文件呢?有一种思路是,混合使用对称加密(如 AES)和非对称加密(如 RSA)。加密时,使用公钥加密 AES 密码,而文件本身使用 AES 加密;而解密时,使用先使用私钥解密出 AES 密码,再使用 AES 密码解密出原始文件。 使用工具 GnuPG(实现了 OpenPGP 协议)可以加密任意大小的文件,它就是这样做的。

3. 处理非对称密码

3.1. 生成密钥

3.1.1. 生成 RSA 密钥

下面命令可生成 RSA 密钥(包含公钥和私钥信息):

$ openssl genrsa -out myrsa.key 2048          # 2048-bit key
$ cat myrsa.key
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqro6cnT+K5FB0CPeUWCYxb9BLEP1TFOItcVTxhz1gdHuwu7k
RFHR5MGZJgyUfyrg6XxKNycmDQl7mTSTMpG0eI8XdPyoyb3K3656o8MEszWX9T5M
jUfKdPRC3Bbt85oV3dhhkfc1htg0cvmpLpW59u1UP2Z05b109Qg8GqvHIkXCLUgc
sB9tJOtB2FigUDWjY4jChh+5IPnozdwl8GhL3VrTXPFkwO/rDS8DHPqFdmWhbsOo
7y0KRj6YekucJ4Q34TvScJ+DNYQcGi8l67DIwVcd7C8/6b/m2Ru3+9if5miXsS2j
sNLOukkSUwrhfqoBGqKuUIKgmyV23s6iWAEqqQIDAQABAoIBAE623gu3dRiROE7G
utG6P7WsoFfQXWB7gySLfjxxTaA1MmgdzJDTSHq35+xrEGwxUNFVxMH5Asov/RR9
8P/3vcV389C0TP32y3ql71VhrOETbKRdvN3Go8mYdNsUl1EhUcOe6B1sZPlu5X+9
LAuWbM80TQuOKYdi+nGfAlcpq/5Yefv1hDi6ArQ12fx/V3lQXohb5XKE8oufRBG9
+l/T7cAzy9ZQdaiEh/19tl8lFo6O1sKa7xm9nB/C2pdBbUQt4M35AlQ6WNDGOAeR
VLpkXNHmcilTJftxyx+S0RNaey3xjL9fSmcfn1IaMTip79F1/iQ83HFSSaO2Dr1U
h3VMhIECgYEA4de8b3lp1ihMcSo2diVhwyevpt0G0MqbDeGCxiehVVvsAZ4XtEkM
5jlbOAs89uFkZlUWH23gBnQQXFMeI3gkqPlbDtkJl2RHxNpE4KqTV3XnpfZ0U/Lx
yyh6DtBdpIjrkSlJaW0dxKkAt9z6+14FePNMziKn/qOqsHg0/zZKHG0CgYEAwYZr
EtQslH56xa4fSMw1v+WuSl+a3TeEEXn9OmOZGObzxE61Qi8kSRA80UOHSSVT4DJn
GcQokW7TZEKYDIfU6JyyMpG3kH43DBoVRglBk0Q5JLrJF+WGAPk9aSJviivVluQ9
V2w4vxb2lYo7v2Wo8NpQPorba8LAF4DNg97Iqa0CgYEAobLANSQ+Fdp2mNO7eK3d
KEhi6Fr6RUW67J5Y7p1zUtVkzeeuWyOue6v3VtIdDTplkys6krgtnRE+oYvVWVnt
DZqzipb02hMvm48Xn7AhnI5LlDU4Jt8cJfROKAsh8OsjlqRz7mr01FiYrgwnGxC/
ZFD23eRMWfI/BOicMVpih6UCgYBO/9E7yXM9VvhFNBQ/QmV6pYblg2uTfHMkMzkl
Gb1IhhbifwLNNrNIRCGfh0J1oJBByDGAOiwZWjVfCzRIgTZvkm/H5uYZTPypqwge
I+8p78Kn9LvcTmzKfvQLs+v2anhxdVB5HIt5riUQ3HIRaq1xTJ1POp3huolxzrmW
aF5frQKBgGc7uKjwZSMEB+U54xVfgWd3FZcRuiNz41+Zl5oZWKgysPP00aY/Rby8
XWtd/nYOgOVLQNkGYgUC3yGJNAO8R26AbWWKBqiAwvgFiHTGr6qZ7SEVwYqm7aCu
7FE68A/cOJhCrms2fPeQZRaRlmGkQKRA5RmtYElxsu/YRjwykQci
-----END RSA PRIVATE KEY-----

使用 openssl rsa -pubout 命令可以从生成的 myrsa.key 文件中导出 X.509 格式的 RSA 公钥,如:

$ openssl rsa -in myrsa.key -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqro6cnT+K5FB0CPeUWCY
xb9BLEP1TFOItcVTxhz1gdHuwu7kRFHR5MGZJgyUfyrg6XxKNycmDQl7mTSTMpG0
eI8XdPyoyb3K3656o8MEszWX9T5MjUfKdPRC3Bbt85oV3dhhkfc1htg0cvmpLpW5
9u1UP2Z05b109Qg8GqvHIkXCLUgcsB9tJOtB2FigUDWjY4jChh+5IPnozdwl8GhL
3VrTXPFkwO/rDS8DHPqFdmWhbsOo7y0KRj6YekucJ4Q34TvScJ+DNYQcGi8l67DI
wVcd7C8/6b/m2Ru3+9if5miXsS2jsNLOukkSUwrhfqoBGqKuUIKgmyV23s6iWAEq
qQIDAQAB
-----END PUBLIC KEY-----

X.509 公钥格式以 -----BEGIN PUBLIC KEY----- 开始, -----END PUBLIC KEY----- 结束。还有另一种公钥格式:PKCS1 公钥格式,这种公钥格式以 -----BEGIN RSA PUBLIC KEY----- 开始, -----END RSA PUBLIC KEY----- 结束。

使用下面命令可从 RSA 私钥中导出 PKCS1 格式的公钥,如:

$ openssl rsa -in myrsa.key -RSAPublicKey_out
writing RSA key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAqro6cnT+K5FB0CPeUWCYxb9BLEP1TFOItcVTxhz1gdHuwu7kRFHR
5MGZJgyUfyrg6XxKNycmDQl7mTSTMpG0eI8XdPyoyb3K3656o8MEszWX9T5MjUfK
dPRC3Bbt85oV3dhhkfc1htg0cvmpLpW59u1UP2Z05b109Qg8GqvHIkXCLUgcsB9t
JOtB2FigUDWjY4jChh+5IPnozdwl8GhL3VrTXPFkwO/rDS8DHPqFdmWhbsOo7y0K
Rj6YekucJ4Q34TvScJ+DNYQcGi8l67DIwVcd7C8/6b/m2Ru3+9if5miXsS2jsNLO
ukkSUwrhfqoBGqKuUIKgmyV23s6iWAEqqQIDAQAB
-----END RSA PUBLIC KEY-----

3.1.2. X.509(BEGIN PUBLIC KEY)和 PKCS1(BEGIN RSA PUBLIC KEY)两个公钥格式的相互转换

从 X.509 公钥格式转换为 PKCS1 公钥格式:

$ openssl rsa -pubin -in pubkey.pem -RSAPublicKey_out       # 从 X.509 公钥格式转换为 PKCS1 公钥格式
writing RSA key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAqro6cnT+K5FB0CPeUWCYxb9BLEP1TFOItcVTxhz1gdHuwu7kRFHR
5MGZJgyUfyrg6XxKNycmDQl7mTSTMpG0eI8XdPyoyb3K3656o8MEszWX9T5MjUfK
dPRC3Bbt85oV3dhhkfc1htg0cvmpLpW59u1UP2Z05b109Qg8GqvHIkXCLUgcsB9t
JOtB2FigUDWjY4jChh+5IPnozdwl8GhL3VrTXPFkwO/rDS8DHPqFdmWhbsOo7y0K
Rj6YekucJ4Q34TvScJ+DNYQcGi8l67DIwVcd7C8/6b/m2Ru3+9if5miXsS2jsNLO
ukkSUwrhfqoBGqKuUIKgmyV23s6iWAEqqQIDAQAB
-----END RSA PUBLIC KEY-----

从 PKCS1 公钥格式转换为 X.509 公钥格式:

$ openssl rsa -RSAPublicKey_in -in pubkey_pkcs1.pem -pubout # 从 PKCS1 公钥格式转换为 X.509 公钥格式
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqro6cnT+K5FB0CPeUWCY
xb9BLEP1TFOItcVTxhz1gdHuwu7kRFHR5MGZJgyUfyrg6XxKNycmDQl7mTSTMpG0
eI8XdPyoyb3K3656o8MEszWX9T5MjUfKdPRC3Bbt85oV3dhhkfc1htg0cvmpLpW5
9u1UP2Z05b109Qg8GqvHIkXCLUgcsB9tJOtB2FigUDWjY4jChh+5IPnozdwl8GhL
3VrTXPFkwO/rDS8DHPqFdmWhbsOo7y0KRj6YekucJ4Q34TvScJ+DNYQcGi8l67DI
wVcd7C8/6b/m2Ru3+9if5miXsS2jsNLOukkSUwrhfqoBGqKuUIKgmyV23s6iWAEq
qQIDAQAB
-----END PUBLIC KEY-----

3.1.3. 查看 RSA 密钥

使用 -text 可以查看 RSA 私钥相关信息,如:

$ openssl rsa -in myrsa.key -text
Private-Key: (2048 bit)
modulus:
    00:aa:ba:3a:72:74:fe:2b:91:41:d0:23:de:51:60:
    98:c5:bf:41:2c:43:f5:4c:53:88:b5:c5:53:c6:1c:
    f5:81:d1:ee:c2:ee:e4:44:51:d1:e4:c1:99:26:0c:
    94:7f:2a:e0:e9:7c:4a:37:27:26:0d:09:7b:99:34:
    93:32:91:b4:78:8f:17:74:fc:a8:c9:bd:ca:df:ae:
    7a:a3:c3:04:b3:35:97:f5:3e:4c:8d:47:ca:74:f4:
    42:dc:16:ed:f3:9a:15:dd:d8:61:91:f7:35:86:d8:
    34:72:f9:a9:2e:95:b9:f6:ed:54:3f:66:74:e5:bd:
    74:f5:08:3c:1a:ab:c7:22:45:c2:2d:48:1c:b0:1f:
    6d:24:eb:41:d8:58:a0:50:35:a3:63:88:c2:86:1f:
    b9:20:f9:e8:cd:dc:25:f0:68:4b:dd:5a:d3:5c:f1:
    64:c0:ef:eb:0d:2f:03:1c:fa:85:76:65:a1:6e:c3:
    a8:ef:2d:0a:46:3e:98:7a:4b:9c:27:84:37:e1:3b:
    d2:70:9f:83:35:84:1c:1a:2f:25:eb:b0:c8:c1:57:
    1d:ec:2f:3f:e9:bf:e6:d9:1b:b7:fb:d8:9f:e6:68:
    97:b1:2d:a3:b0:d2:ce:ba:49:12:53:0a:e1:7e:aa:
    01:1a:a2:ae:50:82:a0:9b:25:76:de:ce:a2:58:01:
    2a:a9
publicExponent: 65537 (0x10001)
privateExponent:
    4e:b6:de:0b:b7:75:18:91:38:4e:c6:ba:d1:ba:3f:
    b5:ac:a0:57:d0:5d:60:7b:83:24:8b:7e:3c:71:4d:
    a0:35:32:68:1d:cc:90:d3:48:7a:b7:e7:ec:6b:10:
    6c:31:50:d1:55:c4:c1:f9:02:ca:2f:fd:14:7d:f0:
    ff:f7:bd:c5:77:f3:d0:b4:4c:fd:f6:cb:7a:a5:ef:
    55:61:ac:e1:13:6c:a4:5d:bc:dd:c6:a3:c9:98:74:
    db:14:97:51:21:51:c3:9e:e8:1d:6c:64:f9:6e:e5:
    7f:bd:2c:0b:96:6c:cf:34:4d:0b:8e:29:87:62:fa:
    71:9f:02:57:29:ab:fe:58:79:fb:f5:84:38:ba:02:
    b4:35:d9:fc:7f:57:79:50:5e:88:5b:e5:72:84:f2:
    8b:9f:44:11:bd:fa:5f:d3:ed:c0:33:cb:d6:50:75:
    a8:84:87:fd:7d:b6:5f:25:16:8e:8e:d6:c2:9a:ef:
    19:bd:9c:1f:c2:da:97:41:6d:44:2d:e0:cd:f9:02:
    54:3a:58:d0:c6:38:07:91:54:ba:64:5c:d1:e6:72:
    29:53:25:fb:71:cb:1f:92:d1:13:5a:7b:2d:f1:8c:
    bf:5f:4a:67:1f:9f:52:1a:31:38:a9:ef:d1:75:fe:
    24:3c:dc:71:52:49:a3:b6:0e:bd:54:87:75:4c:84:
    81
prime1:
    00:e1:d7:bc:6f:79:69:d6:28:4c:71:2a:36:76:25:
    61:c3:27:af:a6:dd:06:d0:ca:9b:0d:e1:82:c6:27:
    a1:55:5b:ec:01:9e:17:b4:49:0c:e6:39:5b:38:0b:
    3c:f6:e1:64:66:55:16:1f:6d:e0:06:74:10:5c:53:
    1e:23:78:24:a8:f9:5b:0e:d9:09:97:64:47:c4:da:
    44:e0:aa:93:57:75:e7:a5:f6:74:53:f2:f1:cb:28:
    7a:0e:d0:5d:a4:88:eb:91:29:49:69:6d:1d:c4:a9:
    00:b7:dc:fa:fb:5e:05:78:f3:4c:ce:22:a7:fe:a3:
    aa:b0:78:34:ff:36:4a:1c:6d
prime2:
    00:c1:86:6b:12:d4:2c:94:7e:7a:c5:ae:1f:48:cc:
    35:bf:e5:ae:4a:5f:9a:dd:37:84:11:79:fd:3a:63:
    99:18:e6:f3:c4:4e:b5:42:2f:24:49:10:3c:d1:43:
    87:49:25:53:e0:32:67:19:c4:28:91:6e:d3:64:42:
    98:0c:87:d4:e8:9c:b2:32:91:b7:90:7e:37:0c:1a:
    15:46:09:41:93:44:39:24:ba:c9:17:e5:86:00:f9:
    3d:69:22:6f:8a:2b:d5:96:e4:3d:57:6c:38:bf:16:
    f6:95:8a:3b:bf:65:a8:f0:da:50:3e:8a:db:6b:c2:
    c0:17:80:cd:83:de:c8:a9:ad
exponent1:
    00:a1:b2:c0:35:24:3e:15:da:76:98:d3:bb:78:ad:
    dd:28:48:62:e8:5a:fa:45:45:ba:ec:9e:58:ee:9d:
    73:52:d5:64:cd:e7:ae:5b:23:ae:7b:ab:f7:56:d2:
    1d:0d:3a:65:93:2b:3a:92:b8:2d:9d:11:3e:a1:8b:
    d5:59:59:ed:0d:9a:b3:8a:96:f4:da:13:2f:9b:8f:
    17:9f:b0:21:9c:8e:4b:94:35:38:26:df:1c:25:f4:
    4e:28:0b:21:f0:eb:23:96:a4:73:ee:6a:f4:d4:58:
    98:ae:0c:27:1b:10:bf:64:50:f6:dd:e4:4c:59:f2:
    3f:04:e8:9c:31:5a:62:87:a5
exponent2:
    4e:ff:d1:3b:c9:73:3d:56:f8:45:34:14:3f:42:65:
    7a:a5:86:e5:83:6b:93:7c:73:24:33:39:25:19:bd:
    48:86:16:e2:7f:02:cd:36:b3:48:44:21:9f:87:42:
    75:a0:90:41:c8:31:80:3a:2c:19:5a:35:5f:0b:34:
    48:81:36:6f:92:6f:c7:e6:e6:19:4c:fc:a9:ab:08:
    1e:23:ef:29:ef:c2:a7:f4:bb:dc:4e:6c:ca:7e:f4:
    0b:b3:eb:f6:6a:78:71:75:50:79:1c:8b:79:ae:25:
    10:dc:72:11:6a:ad:71:4c:9d:4f:3a:9d:e1:ba:89:
    71:ce:b9:96:68:5e:5f:ad
coefficient:
    67:3b:b8:a8:f0:65:23:04:07:e5:39:e3:15:5f:81:
    67:77:15:97:11:ba:23:73:e3:5f:99:97:9a:19:58:
    a8:32:b0:f3:f4:d1:a6:3f:45:bc:bc:5d:6b:5d:fe:
    76:0e:80:e5:4b:40:d9:06:62:05:02:df:21:89:34:
    03:bc:47:6e:80:6d:65:8a:06:a8:80:c2:f8:05:88:
    74:c6:af:aa:99:ed:21:15:c1:8a:a6:ed:a0:ae:ec:
    51:3a:f0:0f:dc:38:98:42:ae:6b:36:7c:f7:90:65:
    16:91:96:61:a4:40:a4:40:e5:19:ad:60:49:71:b2:
    ef:d8:46:3c:32:91:07:22
......

查看 RSA X.509 格式公钥:

$ openssl rsa -pubin -in pubkey.pem -text
Public-Key: (2048 bit)
Modulus:
    00:aa:ba:3a:72:74:fe:2b:91:41:d0:23:de:51:60:
    98:c5:bf:41:2c:43:f5:4c:53:88:b5:c5:53:c6:1c:
    f5:81:d1:ee:c2:ee:e4:44:51:d1:e4:c1:99:26:0c:
    94:7f:2a:e0:e9:7c:4a:37:27:26:0d:09:7b:99:34:
    93:32:91:b4:78:8f:17:74:fc:a8:c9:bd:ca:df:ae:
    7a:a3:c3:04:b3:35:97:f5:3e:4c:8d:47:ca:74:f4:
    42:dc:16:ed:f3:9a:15:dd:d8:61:91:f7:35:86:d8:
    34:72:f9:a9:2e:95:b9:f6:ed:54:3f:66:74:e5:bd:
    74:f5:08:3c:1a:ab:c7:22:45:c2:2d:48:1c:b0:1f:
    6d:24:eb:41:d8:58:a0:50:35:a3:63:88:c2:86:1f:
    b9:20:f9:e8:cd:dc:25:f0:68:4b:dd:5a:d3:5c:f1:
    64:c0:ef:eb:0d:2f:03:1c:fa:85:76:65:a1:6e:c3:
    a8:ef:2d:0a:46:3e:98:7a:4b:9c:27:84:37:e1:3b:
    d2:70:9f:83:35:84:1c:1a:2f:25:eb:b0:c8:c1:57:
    1d:ec:2f:3f:e9:bf:e6:d9:1b:b7:fb:d8:9f:e6:68:
    97:b1:2d:a3:b0:d2:ce:ba:49:12:53:0a:e1:7e:aa:
    01:1a:a2:ae:50:82:a0:9b:25:76:de:ce:a2:58:01:
    2a:a9
Exponent: 65537 (0x10001)
......

查看 RSA PKCS1 格式公钥:

openssl rsa -RSAPublicKey_in -in pubkey_pkcs1.pem -text
Public-Key: (2048 bit)
Modulus:
    00:aa:ba:3a:72:74:fe:2b:91:41:d0:23:de:51:60:
    98:c5:bf:41:2c:43:f5:4c:53:88:b5:c5:53:c6:1c:
    f5:81:d1:ee:c2:ee:e4:44:51:d1:e4:c1:99:26:0c:
    94:7f:2a:e0:e9:7c:4a:37:27:26:0d:09:7b:99:34:
    93:32:91:b4:78:8f:17:74:fc:a8:c9:bd:ca:df:ae:
    7a:a3:c3:04:b3:35:97:f5:3e:4c:8d:47:ca:74:f4:
    42:dc:16:ed:f3:9a:15:dd:d8:61:91:f7:35:86:d8:
    34:72:f9:a9:2e:95:b9:f6:ed:54:3f:66:74:e5:bd:
    74:f5:08:3c:1a:ab:c7:22:45:c2:2d:48:1c:b0:1f:
    6d:24:eb:41:d8:58:a0:50:35:a3:63:88:c2:86:1f:
    b9:20:f9:e8:cd:dc:25:f0:68:4b:dd:5a:d3:5c:f1:
    64:c0:ef:eb:0d:2f:03:1c:fa:85:76:65:a1:6e:c3:
    a8:ef:2d:0a:46:3e:98:7a:4b:9c:27:84:37:e1:3b:
    d2:70:9f:83:35:84:1c:1a:2f:25:eb:b0:c8:c1:57:
    1d:ec:2f:3f:e9:bf:e6:d9:1b:b7:fb:d8:9f:e6:68:
    97:b1:2d:a3:b0:d2:ce:ba:49:12:53:0a:e1:7e:aa:
    01:1a:a2:ae:50:82:a0:9b:25:76:de:ce:a2:58:01:
    2a:a9
Exponent: 65537 (0x10001)
......

3.2. Certificates AKA x509

3.2.1. x509 证书编码格式(PEM,DER)

有两种常用的 x509 证书编码格式:PEM(纯文本,以 -----BEGIN CERTIFICATE----- 开始,以 -----END CERTIFICATE----- 结束,中间是 base64 编码)、DER(二进制编码,直接用文本编辑器打开是乱码)。PEM 格式证书文件常用 .pem 后缀,DER 格式证书文件常用 .der 后缀;有时证书文件使用 .crt 后缀,这时它可能是 PEM 格式,也可能是 DER 格式。

说明:当我们提到“证书格式”时,有时还会遇到 .pfx 后缀或者 .p12 后缀的证书,它们是一种同时包含私钥(应该绝对保密)、公钥及公钥证书的文件(二进制编码),文件本身可以用密码加密,相关标准可参考 pkcs12 。而本节所说的 x509 证书是指公钥证书,它不会包含私钥。

3.2.1.1. PEM 和 DER 的相互转换(-outform)

指定 -outform pem|der 可以进行 PEM 和 DER 的相互转换。如:

$ openssl x509 -in cert.pem -outform der -out cert.der             # 从PEM到DER的转换
$ openssl x509 -in cert.der -inform der -outform pem -out cert.pem # 从DER到PEM的转换

3.2.2. 获取 https 服务器的证书

当我们访问 https 服务器时,在 tls 的 handshake 阶段 client 会获取 server 的证书。

下面脚本可以把 https 服务器证书显示到 stdout:

#!/bin/sh
#
# usage: retrieve-cert.sh remote.host.name [port]
#
# This script is copied from http://www.lagmonster.org/docs/openssl.html#cert-retrieve
REMHOST=$1
REMPORT=${2:-443}

echo |\
openssl s_client -connect ${REMHOST}:${REMPORT} 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

比如,下载 baidu.com 的证书:

$ ./retrieve-cert.sh baidu.com 443
-----BEGIN CERTIFICATE-----
MIIHKDCCBhCgAwIBAgIQCdi4dJ3JNIJeg1mgZUbAmTANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwNDAzMDAwMDAwWhcN
MTkwNDAzMTIwMDAwWjCBmDELMAkGA1UEBhMCQ04xEDAOBgNVBAcTB0JlaWppbmcx
OTA3BgNVBAoTMEJlaUppbmcgQmFpZHUgTmV0Y29tIFNjaWVuY2UgVGVjaG5vbG9n
eSBDby4sIEx0ZDElMCMGA1UECxMcc2VydmljZSBvcGVyYXRpb24gZGVwYXJ0bWVu
dDEVMBMGA1UEAxMMd3d3LmJhaWR1LmNuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxfCR6IaIbCkh5kwSSkcvj7DDjx4eGMeqPDNoGdPVZ62muX6gLIPK
RqvpcDD9Dxz86oxgh58tWJGnSXk4gaeKOpAfm8JoxegrRmE5uOMjM+F1U50rFscx
w9h1czPkPpwLV3l+zP8kwVLtWLuesRMVpPgyFXr5W5db6r1Ixh0YjoQB1S1OalZh
j/7BKnMpj/Fg3/tAqu0ONBDMcJmD4e3Qgupd8PmZmidcwWGb3JW7tBm4y78CKQFW
b6eW5zzEwPnKHPJbHwmOTHgK0V03eXShlLVbURytO78r69P5Zp6bbVS8AK7e220k
IOhDodV/AX6jAxIIvdiBD649se7eqcgpwQIDAQABo4IDtjCCA7IwHwYDVR0jBBgw
FoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFHcpf65dezsVZo5DXWOZ
avbPOoc4MIH0BgNVHREEgewwgemCCGJhaWR1LmNuggliYWlkdS5jb22CDGJhaWR1
LmNvbS5jboILdy5iYWlkdS5jb22CDHd3LmJhaWR1LmNvbYIMd3d3LmJhaWR1LmNu
ghB3d3cuYmFpZHUuY29tLmNughB3d3cuYmFpZHUuY29tLmhrggx3d3cuYmFpZHUu
aGuCEHd3dy5iYWlkdS5uZXQuYXWCEHd3dy5iYWlkdS5uZXQucGiCEHd3dy5iYWlk
dS5uZXQudHeCEHd3dy5iYWlkdS5uZXQudm6CDnd3d3cuYmFpZHUuY29tghF3d3d3
LmJhaWR1LmNvbS5jbjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMCMGsGA1UdHwRkMGIwL6AtoCuGKWh0dHA6Ly9jcmwzLmRpZ2lj
ZXJ0LmNvbS9zc2NhLXNoYTItZzYuY3JsMC+gLaArhilodHRwOi8vY3JsNC5kaWdp
Y2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwB
ATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgG
BmeBDAECAjB8BggrBgEFBQcBAQRwMG4wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw
LmRpZ2ljZXJ0LmNvbTBGBggrBgEFBQcwAoY6aHR0cDovL2NhY2VydHMuZGlnaWNl
cnQuY29tL0RpZ2lDZXJ0U0hBMlNlY3VyZVNlcnZlckNBLmNydDAJBgNVHRMEAjAA
MIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5
G9+443fNDsgN3BAAAAFiinOKcwAABAMARzBFAiEAyQLGZj3uzygOaWt53R1Ji3RD
Cc7Lz6HUaEWr/zFmiUICIBCLM91ecE3U2cNutgS1utN3zjDEMPNHmAwUOiRMXbWP
AHYAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RMAAAFiinOLnwAABAMA
RzBFAiAoUXB7X5N85XIw/bVouSFq7xReRS89hIeGELWODBAXmAIhAMUcYHdSnypC
2hr17OzaP742IV9CM1nFczFNdargkkbxMA0GCSqGSIb3DQEBCwUAA4IBAQAX+Sc3
rS9iZBPvqdL5mLAXaprHwR4L/hSNkknwkmh0+JJlRYrXu0T9qecUXDst093HsTYk
MIxicSXga2wW+SNTZLj/6vXrCZs39ZvIZYAj2L0m01EuVHsTLIKVoxi+aZpXfUNB
WRDB1XAnZbNDwWl7mQtAwr3/wIJnGtPuSHzWYkY4Aoi5UjMnh0I3ndljqTKBTCi0
F7iwcptcyihwsKojdfOBF4WbwQLA/JMh2fhF062zUWCz3L76zmzQ6007IIUurH0/
5Yc3daUgxeV8J8qHVo7NOwbaPnrq1gTfzO0nw5oFtyJeqgyQ/BCaTXxyauDbprSP
rPhAyWO3cT1sMaqu
-----END CERTIFICATE-----

注:你不能在代理服务器后面运行上面脚本。从 openssl v1.1.0 起 openssl s_client 才支持 -proxy 选项,可参考:https://stackoverflow.com/questions/3220419/openssl-s-client-using-a-proxy

3.2.3. 查看 x509 证书内容(-text)

使用 -text 可以 dump 出证书的详细信息。如:

$ openssl x509 -in baidu.com.pem -text         # 查看PEM证书详细信息(DER格式时应指定-inform der)
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            09:d8:b8:74:9d:c9:34:82:5e:83:59:a0:65:46:c0:99
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=DigiCert Inc, CN=DigiCert SHA2 Secure Server CA
        Validity
            Not Before: Apr  3 00:00:00 2018 GMT
            Not After : Apr  3 12:00:00 2019 GMT
        Subject: C=CN, L=Beijing, O=BeiJing Baidu Netcom Science Technology Co., Ltd, OU=service operation department, CN=www.baidu.cn
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c5:f0:91:e8:86:88:6c:29:21:e6:4c:12:4a:47:
                    2f:8f:b0:c3:8f:1e:1e:18:c7:aa:3c:33:68:19:d3:
                    d5:67:ad:a6:b9:7e:a0:2c:83:ca:46:ab:e9:70:30:
                    fd:0f:1c:fc:ea:8c:60:87:9f:2d:58:91:a7:49:79:
                    38:81:a7:8a:3a:90:1f:9b:c2:68:c5:e8:2b:46:61:
                    39:b8:e3:23:33:e1:75:53:9d:2b:16:c7:31:c3:d8:
                    75:73:33:e4:3e:9c:0b:57:79:7e:cc:ff:24:c1:52:
                    ed:58:bb:9e:b1:13:15:a4:f8:32:15:7a:f9:5b:97:
                    5b:ea:bd:48:c6:1d:18:8e:84:01:d5:2d:4e:6a:56:
                    61:8f:fe:c1:2a:73:29:8f:f1:60:df:fb:40:aa:ed:
                    0e:34:10:cc:70:99:83:e1:ed:d0:82:ea:5d:f0:f9:
                    99:9a:27:5c:c1:61:9b:dc:95:bb:b4:19:b8:cb:bf:
                    02:29:01:56:6f:a7:96:e7:3c:c4:c0:f9:ca:1c:f2:
                    5b:1f:09:8e:4c:78:0a:d1:5d:37:79:74:a1:94:b5:
                    5b:51:1c:ad:3b:bf:2b:eb:d3:f9:66:9e:9b:6d:54:
                    bc:00:ae:de:db:6d:24:20:e8:43:a1:d5:7f:01:7e:
                    a3:03:12:08:bd:d8:81:0f:ae:3d:b1:ee:de:a9:c8:
                    29:c1
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier:
                keyid:0F:80:61:1C:82:31:61:D5:2F:28:E7:8D:46:38:B4:2C:E1:C6:D9:E2

            X509v3 Subject Key Identifier:
                77:29:7F:AE:5D:7B:3B:15:66:8E:43:5D:63:99:6A:F6:CF:3A:87:38
            X509v3 Subject Alternative Name:
                DNS:baidu.cn, DNS:baidu.com, DNS:baidu.com.cn, DNS:w.baidu.com, DNS:ww.baidu.com, DNS:www.baidu.cn, DNS:www.baidu.com.cn, DNS:www.baidu.com.hk, DNS:www.baidu.hk, DNS:www.baidu.net.au, DNS:www.baidu.net.ph, DNS:www.baidu.net.tw, DNS:www.baidu.net.vn, DNS:wwww.baidu.com, DNS:wwww.baidu.com.cn
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 CRL Distribution Points:

                Full Name:
                  URI:http://crl3.digicert.com/ssca-sha2-g6.crl

                Full Name:
                  URI:http://crl4.digicert.com/ssca-sha2-g6.crl

            X509v3 Certificate Policies:
                Policy: 2.16.840.1.114412.1.1
                  CPS: https://www.digicert.com/CPS
                Policy: 2.23.140.1.2.2

            Authority Information Access:
                OCSP - URI:http://ocsp.digicert.com
                CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt

            X509v3 Basic Constraints:
                CA:FALSE
            CT Precertificate SCTs:
                Signed Certificate Timestamp:
                    Version   : v1(0)
                    Log ID    : A4:B9:09:90:B4:18:58:14:87:BB:13:A2:CC:67:70:0A:
                                3C:35:98:04:F9:1B:DF:B8:E3:77:CD:0E:C8:0D:DC:10
                    Timestamp : Apr  3 07:40:50.675 2018 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:21:00:C9:02:C6:66:3D:EE:CF:28:0E:69:6B:
                                79:DD:1D:49:8B:74:43:09:CE:CB:CF:A1:D4:68:45:AB:
                                FF:31:66:89:42:02:20:10:8B:33:DD:5E:70:4D:D4:D9:
                                C3:6E:B6:04:B5:BA:D3:77:CE:30:C4:30:F3:47:98:0C:
                                14:3A:24:4C:5D:B5:8F
                Signed Certificate Timestamp:
                    Version   : v1(0)
                    Log ID    : 6F:53:76:AC:31:F0:31:19:D8:99:00:A4:51:15:FF:77:
                                15:1C:11:D9:02:C1:00:29:06:8D:B2:08:9A:37:D9:13
                    Timestamp : Apr  3 07:40:50.975 2018 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:20:28:51:70:7B:5F:93:7C:E5:72:30:FD:B5:
                                68:B9:21:6A:EF:14:5E:45:2F:3D:84:87:86:10:B5:8E:
                                0C:10:17:98:02:21:00:C5:1C:60:77:52:9F:2A:42:DA:
                                1A:F5:EC:EC:DA:3F:BE:36:21:5F:42:33:59:C5:73:31:
                                4D:75:AA:E0:92:46:F1
    Signature Algorithm: sha256WithRSAEncryption
         17:f9:27:37:ad:2f:62:64:13:ef:a9:d2:f9:98:b0:17:6a:9a:
         c7:c1:1e:0b:fe:14:8d:92:49:f0:92:68:74:f8:92:65:45:8a:
         d7:bb:44:fd:a9:e7:14:5c:3b:2d:d3:dd:c7:b1:36:24:30:8c:
         62:71:25:e0:6b:6c:16:f9:23:53:64:b8:ff:ea:f5:eb:09:9b:
         37:f5:9b:c8:65:80:23:d8:bd:26:d3:51:2e:54:7b:13:2c:82:
         95:a3:18:be:69:9a:57:7d:43:41:59:10:c1:d5:70:27:65:b3:
         43:c1:69:7b:99:0b:40:c2:bd:ff:c0:82:67:1a:d3:ee:48:7c:
         d6:62:46:38:02:88:b9:52:33:27:87:42:37:9d:d9:63:a9:32:
         81:4c:28:b4:17:b8:b0:72:9b:5c:ca:28:70:b0:aa:23:75:f3:
         81:17:85:9b:c1:02:c0:fc:93:21:d9:f8:45:d3:ad:b3:51:60:
         b3:dc:be:fa:ce:6c:d0:eb:4d:3b:20:85:2e:ac:7d:3f:e5:87:
         37:75:a5:20:c5:e5:7c:27:ca:87:56:8e:cd:3b:06:da:3e:7a:
         ea:d6:04:df:cc:ed:27:c3:9a:05:b7:22:5e:aa:0c:90:fc:10:
         9a:4d:7c:72:6a:e0:db:a6:b4:8f:ac:f8:40:c9:63:b7:71:3d:
         6c:31:aa:ae
-----BEGIN CERTIFICATE-----
MIIHKDCCBhCgAwIBAgIQCdi4dJ3JNIJeg1mgZUbAmTANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwNDAzMDAwMDAwWhcN
MTkwNDAzMTIwMDAwWjCBmDELMAkGA1UEBhMCQ04xEDAOBgNVBAcTB0JlaWppbmcx
OTA3BgNVBAoTMEJlaUppbmcgQmFpZHUgTmV0Y29tIFNjaWVuY2UgVGVjaG5vbG9n
eSBDby4sIEx0ZDElMCMGA1UECxMcc2VydmljZSBvcGVyYXRpb24gZGVwYXJ0bWVu
dDEVMBMGA1UEAxMMd3d3LmJhaWR1LmNuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxfCR6IaIbCkh5kwSSkcvj7DDjx4eGMeqPDNoGdPVZ62muX6gLIPK
RqvpcDD9Dxz86oxgh58tWJGnSXk4gaeKOpAfm8JoxegrRmE5uOMjM+F1U50rFscx
w9h1czPkPpwLV3l+zP8kwVLtWLuesRMVpPgyFXr5W5db6r1Ixh0YjoQB1S1OalZh
j/7BKnMpj/Fg3/tAqu0ONBDMcJmD4e3Qgupd8PmZmidcwWGb3JW7tBm4y78CKQFW
b6eW5zzEwPnKHPJbHwmOTHgK0V03eXShlLVbURytO78r69P5Zp6bbVS8AK7e220k
IOhDodV/AX6jAxIIvdiBD649se7eqcgpwQIDAQABo4IDtjCCA7IwHwYDVR0jBBgw
FoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFHcpf65dezsVZo5DXWOZ
avbPOoc4MIH0BgNVHREEgewwgemCCGJhaWR1LmNuggliYWlkdS5jb22CDGJhaWR1
LmNvbS5jboILdy5iYWlkdS5jb22CDHd3LmJhaWR1LmNvbYIMd3d3LmJhaWR1LmNu
ghB3d3cuYmFpZHUuY29tLmNughB3d3cuYmFpZHUuY29tLmhrggx3d3cuYmFpZHUu
aGuCEHd3dy5iYWlkdS5uZXQuYXWCEHd3dy5iYWlkdS5uZXQucGiCEHd3dy5iYWlk
dS5uZXQudHeCEHd3dy5iYWlkdS5uZXQudm6CDnd3d3cuYmFpZHUuY29tghF3d3d3
LmJhaWR1LmNvbS5jbjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMCMGsGA1UdHwRkMGIwL6AtoCuGKWh0dHA6Ly9jcmwzLmRpZ2lj
ZXJ0LmNvbS9zc2NhLXNoYTItZzYuY3JsMC+gLaArhilodHRwOi8vY3JsNC5kaWdp
Y2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwB
ATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgG
BmeBDAECAjB8BggrBgEFBQcBAQRwMG4wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw
LmRpZ2ljZXJ0LmNvbTBGBggrBgEFBQcwAoY6aHR0cDovL2NhY2VydHMuZGlnaWNl
cnQuY29tL0RpZ2lDZXJ0U0hBMlNlY3VyZVNlcnZlckNBLmNydDAJBgNVHRMEAjAA
MIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5
G9+443fNDsgN3BAAAAFiinOKcwAABAMARzBFAiEAyQLGZj3uzygOaWt53R1Ji3RD
Cc7Lz6HUaEWr/zFmiUICIBCLM91ecE3U2cNutgS1utN3zjDEMPNHmAwUOiRMXbWP
AHYAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RMAAAFiinOLnwAABAMA
RzBFAiAoUXB7X5N85XIw/bVouSFq7xReRS89hIeGELWODBAXmAIhAMUcYHdSnypC
2hr17OzaP742IV9CM1nFczFNdargkkbxMA0GCSqGSIb3DQEBCwUAA4IBAQAX+Sc3
rS9iZBPvqdL5mLAXaprHwR4L/hSNkknwkmh0+JJlRYrXu0T9qecUXDst093HsTYk
MIxicSXga2wW+SNTZLj/6vXrCZs39ZvIZYAj2L0m01EuVHsTLIKVoxi+aZpXfUNB
WRDB1XAnZbNDwWl7mQtAwr3/wIJnGtPuSHzWYkY4Aoi5UjMnh0I3ndljqTKBTCi0
F7iwcptcyihwsKojdfOBF4WbwQLA/JMh2fhF062zUWCz3L76zmzQ6007IIUurH0/
5Yc3daUgxeV8J8qHVo7NOwbaPnrq1gTfzO0nw5oFtyJeqgyQ/BCaTXxyauDbprSP
rPhAyWO3cT1sMaqu
-----END CERTIFICATE-----

在上面输出的最后部分,会把证书原始内容直接输出,可通过 -noout 选项抑制证书原始内容的输出。

3.2.3.1. 查询证书的某项信息

除了使用 -text dump 出证书的详细信息,还可以查询指定的某项信息。

查询证书的序列号(选项 -serial ):

$ openssl x509 -in baidu.com.pem -noout -serial
serial=09D8B8749DC934825E8359A06546C099

查询证书的签发者(选项 -issuer ):

$ openssl x509 -in baidu.com.pem -noout -issuer
issuer= /C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA

查询证书的有效期(选项 -dates ):

$ openssl x509 -in baidu.com.pem -noout -dates
notBefore=Apr  3 00:00:00 2018 GMT
notAfter=Apr  3 12:00:00 2019 GMT

导出证书中的公钥(选项 -pubkey ):

$ openssl x509 -in baidu.com.pem -noout -pubkey
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxfCR6IaIbCkh5kwSSkcv
j7DDjx4eGMeqPDNoGdPVZ62muX6gLIPKRqvpcDD9Dxz86oxgh58tWJGnSXk4gaeK
OpAfm8JoxegrRmE5uOMjM+F1U50rFscxw9h1czPkPpwLV3l+zP8kwVLtWLuesRMV
pPgyFXr5W5db6r1Ixh0YjoQB1S1OalZhj/7BKnMpj/Fg3/tAqu0ONBDMcJmD4e3Q
gupd8PmZmidcwWGb3JW7tBm4y78CKQFWb6eW5zzEwPnKHPJbHwmOTHgK0V03eXSh
lLVbURytO78r69P5Zp6bbVS8AK7e220kIOhDodV/AX6jAxIIvdiBD649se7eqcgp
wQIDAQAB
-----END PUBLIC KEY-----

3.3. 申请证书过程(openssl req)

生成 X509 数字证书的流程是:先由用户提交证书申请文件(证书请求的语法标准定义在PKCS#10中),然后由 CA 来签发证书。

3.3.1. 生成证书申请文件(openssl req -new)

证书申请文件主要包括了用户信息、公钥以及一些可选的属性信息,并用自己的私钥给该内容签名。所以,生成证书申请文件时既要有公钥,还要有私钥。

如果你手头有密钥对,想为它生成证书申请文件,可以执行:

$ openssl req -new -key mykey.pem -out myreq.csr        # 你需要交互式地回答一系列问题
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

如果你手头没有密钥对,则生成证书申请文件指定 -newkey 选项可以创建一个密钥对,并为相应公钥生成证书申请文件。如:

$ openssl req -new -newkey rsa:1024 -nodes -keyout mykey.pem -out myreq.csr  # 你需要交互式地回答一系列问题

如果指定 -subj 选项,则不用交互式地回答一系列问题,可直接生成证书申请文件。如:

$ openssl req \
  -new -newkey rsa:1024 -nodes \
  -subj '/CN=www.mydom.com/O=My Dom, Inc./C=US/ST=Oregon/L=Portland' \
  -keyout mykey.pem -out myreq.csr

注 1: -nodes 选项意思是“No DES”,即不加密私钥(不加密上面输出密钥 mykey.pem 中的私钥)。
注 2: subj 选项参数中“CN”域必须和你想部署证书的服务器域名匹配,否则会验证不过。

3.3.1.1. 查看证书申请文件(openssl req -text)

使用 openssl req 命令的 -text 选项可以查看证书申请文件的相关信息。如:

$ openssl req -in myreq.csr -text
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: CN=www.mydom.com, O=My Dom, Inc., C=US, ST=Oregon, L=Portland
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:a5:40:9c:0c:82:80:c1:e6:10:17:db:8e:a8:88:
                    84:a5:72:dc:89:a3:32:d5:9d:eb:ea:74:ca:e5:18:
                    f4:a0:a4:d0:9e:c7:b8:35:f3:d9:ff:05:42:47:30:
                    1a:b0:cc:42:43:11:97:0f:f1:cc:a9:80:5b:db:b3:
                    bc:90:01:67:55:1e:57:6e:22:f1:a4:89:9b:33:40:
                    bf:a0:6f:fa:7b:23:5b:5b:8a:a9:78:e0:d7:ae:ab:
                    18:a1:5e:3f:81:57:85:c1:96:4a:5f:53:16:93:47:
                    20:f2:66:de:b1:95:66:31:fb:ba:5a:9c:b5:09:3a:
                    f6:6c:ef:e9:b3:25:4e:d6:bb
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         31:6c:e3:7f:cc:cc:7c:13:44:bc:0f:0a:24:06:cb:8c:bf:c7:
         ba:93:52:5c:3f:f7:4d:96:44:14:b8:cf:cb:e0:94:d7:e2:4d:
         40:6e:76:2d:f9:d9:4a:79:4c:f6:f4:e3:61:e7:23:0f:43:d9:
         47:8c:95:eb:5f:e6:cc:25:51:2f:9b:07:93:f7:a6:38:78:77:
         01:d6:48:f6:88:33:62:43:c7:e4:c9:0b:1d:d9:93:ea:e1:72:
         ec:48:d4:56:a0:b3:3e:5d:73:86:12:1a:ab:93:33:6c:25:1b:
         be:65:3d:08:99:96:43:47:f2:89:e1:f1:31:69:d5:08:a1:b1:
         ed:23
-----BEGIN CERTIFICATE REQUEST-----
MIIBoDCCAQkCAQAwYDEWMBQGA1UEAwwNd3d3Lm15ZG9tLmNvbTEVMBMGA1UECgwM
TXkgRG9tLCBJbmMuMQswCQYDVQQGEwJVUzEPMA0GA1UECAwGT3JlZ29uMREwDwYD
VQQHDAhQb3J0bGFuZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApUCcDIKA
weYQF9uOqIiEpXLciaMy1Z3r6nTK5Rj0oKTQnse4NfPZ/wVCRzAasMxCQxGXD/HM
qYBb27O8kAFnVR5XbiLxpImbM0C/oG/6eyNbW4qpeODXrqsYoV4/gVeFwZZKX1MW
k0cg8mbesZVmMfu6Wpy1CTr2bO/psyVO1rsCAwEAAaAAMA0GCSqGSIb3DQEBCwUA
A4GBADFs43/MzHwTRLwPCiQGy4y/x7qTUlw/902WRBS4z8vglNfiTUBudi352Up5
TPb042HnIw9D2UeMletf5swlUS+bB5P3pjh4dwHWSPaIM2JDx+TJCx3Zk+rhcuxI
1Fagsz5dc4YSGquTM2wlG75lPQiZlkNH8onh8TFp1Qihse0j
-----END CERTIFICATE REQUEST-----

3.3.2. 向 CA 申请证书(openssl ca)

在实际应用中,用户可以通过向知名 CA 递交证书请求来申请证书。我们可以自己建立的是一个根 CA。首先,准备如配置文件,一般名为 openssl.cnf,其相关配置参见 man 5 openssl.cnf

向自建 CA 申请证书的命令如下:

$ openssl ca -config ./openssl.cnf -in myreq.csr

命令执行成功后,新证书位于 openssl.cnf 文件中 new_certs_dir 配置项所指定的目录中,一般以序号命名,如 01.pem 等。

参考:
基于OpenSSL的CA建立及证书签发
Openssl.conf Walkthru

3.4. Client Certificates AKA pkcs12

在 TLS 双向认证时,不仅 client 要认证 server,server 也需要认证 client,这时 client 需要提供证书。这种证书包含了私钥、公钥及公钥证书等信息,一般保存为 pkcs12 格式(二进制格式)。

下面是生成 pkcs12 证书的例子:

$ openssl pkcs12 -export -out certificate.p12 -inkey privateKey.pem -in certificate.pem    # 会提示输入保护p12文件的密码
Enter Export Password:

3.4.1. 转换 pkcs12 证书为 PEM 格式

curl 命令的 --cert 选项就是指定 client 证书,它默认使用 PEM 格式。

下面命令可以把 pkcs12 证书导出为 PEM 文本格式(保存着公钥证书及私钥文件):

$ openssl pkcs12 -in certificate.p12 -out client.pem -nodes  # 会提示输入p12文件的密码
$ openssl pkcs12 -in certificate.p12 -out client.pem         # 会提示输入p12文件的密码,以及想要设置的私钥保护密码

生成的 client.pem 文件中同时保存着公钥证书及私钥文件,组织方法是直接 concate,如:

$ cat client.pem
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
-----BEGIN ENCRYPTED PRIVATE KEY-----
......
-----END ENCRYPTED PRIVATE KEY-----

4. 其它用途

4.1. 检查 https 网站的证书过期时间

使用 openssl 可以检测 https 网站的证书过期时间,如:

$ echo | openssl s_client -connect redhat.com:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Jul  9 00:00:00 2019 GMT
notAfter=Aug  2 12:00:00 2021 GMT

4.2. 生成随机数

使用 openssl 可以生成随机数,如:

$ openssl rand -hex 1       # 生成 1 字节(8 比特位)随机数,以16 进制字符串显示
7c
$ openssl rand -hex 32      # 生成 32 字节(256 比特位)随机数,以16 进制字符串显示
26d23e5b5cc29a4193dcc03ff496ee5ec872099618571b4046d265647badaf7a
$ openssl rand -base64 1    # 生成 1 字节(8 比特位)随机数,以 base64 编码显示
Rg==
$ openssl rand -base64 8    # 生成 32 字节(256 比特位)随机数,以 base64 编码显示
rTdLXxfSzdw=

4.3. 生成和检测素数

使用 openssl 可以生成和检测素数,如:

$ openssl prime -generate -bits 64            # 生成 64 比特位的素数
14789941230951921899
$ openssl prime -generate -bits 1024          # 生成 1024 比特位的素数
155518510026330114079529185042334126955325635961503752247259297204330426494152665324914364571965572451091043911359107192387374322465763901687156826871735451385749434607151244530011732007529405966851338424255823667161485366418517076669957730866472599318969394859579268446104639981874390502417536323283936218469
$ openssl prime -generate -bits 1024 -safe    # 生成 1024 比特位的 safe prime
139885262543144901576201219028143429524691380969001486169373150284955912804914895414238725423000258730008814839164989854573678989468312037483405484205656589522461593121442252806886208597694248804139790550966062419733033087389060588101161000193926738605299192976720465267946237942664064455886474615163777283543

注:对于一个素数 \(p\) ,如果 \((p-1)/2\) 也是素数,则称为 safe prime。之所以称为 safe prime,是因为两个 safe prime 的乘积可以抵抗 Pollard's p − 1 算法进行因子分解。

下面是测试某个数是否是素数的例子:

$ openssl prime 14789941230951921899
14789941230951921899 is prime
$ openssl prime 155518510026330114079529185042334126955325635961503752247259297204330426494152665324914364571965572451091043911359107192387374322465763901687156826871735451385749434607151244530011732007529405966851338424255823667161485366418517076669957730866472599318969394859579268446104639981874390502417536323283936218469
155518510026330114079529185042334126955325635961503752247259297204330426494152665324914364571965572451091043911359107192387374322465763901687156826871735451385749434607151244530011732007529405966851338424255823667161485366418517076669957730866472599318969394859579268446104639981874390502417536323283936218469 is prime
$ openssl prime 139885262543144901576201219028143429524691380969001486169373150284955912804914895414238725423000258730008814839164989854573678989468312037483405484205656589522461593121442252806886208597694248804139790550966062419733033087389060588101161000193926738605299192976720465267946237942664064455886474615163777283543
139885262543144901576201219028143429524691380969001486169373150284955912804914895414238725423000258730008814839164989854573678989468312037483405484205656589522461593121442252806886208597694248804139790550966062419733033087389060588101161000193926738605299192976720465267946237942664064455886474615163777283543 is prime

Author: cig01

Created: <2018-03-22 Thu>

Last updated: <2021-06-15 Tue>

Creator: Emacs 27.1 (Org mode 9.4)