这篇文章详细讲述一下RSA与证书的相关内容。内容有点多,但都是干货。
RSA算法是由美国三位科学家Rivest、Shamir和Adleman于1976年提出并在1978年正式发表的公开密码算
法,其命名取自三位创始人名字的首字母缩写。该算法基于数论中的大数分解难题,即:根据数论,寻求两个
大素数比较简单,而将它们的乘积分解开则极其困难。
该算法中,用户有两个密钥:公钥 PK={e,n}和私钥 SK={d,n},n 为两个大素数 p和q的乘积(素数p和q一
般为1 0 0位以上的十进制数),e和d满足一定的关系,如只知道e和n并不能求出d。
(1)加密/解密过程
若用整数X表示明文,用整数Y表示密文(X和Y均小于n),则加密和解密运算为:
① 计算n。用户秘密选择两个大素数p和q,计算出n=pq。n称为RSA算法的模数。明文必须能够用小于n的数
来表示。
素数/质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
RSA密钥长度指的是模数的位数,如2048位RSA密钥指的是模数为2048比特的RSA密钥对,常规选值为:1024、2048、4096等。
密文长度就是对给定符合条件的明文加密出来的结果位长,这个是可以确定的,加密后的密文长度跟密钥长度是相同的,也就是模数的长度。
② 计算φ(n)。用户计算出n的欧拉函数φ(n)=(p-1)(q-1)。φ(n)定义为不超过n并与n互素的数的
个数。
③ 选择e。用户从[0,φ(n)-1]中选择一个与φ(n)互素的数e作为公开的加密指数。
④ 计算d。用户计算出满足公式ed=1 modφ(n)的d作为解密指数。
⑤ 得出所需要的公钥和私钥:
实际走一下计算过程
随机选择两个不相等的质数p和q,p = 61,q = 53
计算p和q的乘积n,n = 61×53 = 3233
计算n的欧拉函数φ(n)(这儿用到了欧拉定理)
φ(n) = (p1-1)(p2-1)
φ(3233) = 60x52 = 3120
随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质 ,假设选择了17
计算出d,使得ed % φ(n)=(17*2753)%3120 = 1(如何解出d需要用到辗转相除法),得到d为2753
形成公钥(e, n) =(17, 3223) ,私钥 (d, n) = (2753, 3223)
//计算欧拉函数值
func euler(n int) int {
ans := n
for i := 2; i*i <= ans; i++ {
if n%i == 0 {
ans = ans / i * (i - 1)
// 将相同的因子除去
for n%i == 0 {
n /= i
}
}
}
if n > 1 {
ans = ans / n * (n - 1)
}
return ans
}
用公钥加密,假设选择A,ASCII为65,即m=65
m^e=c(modn)
即 65 ^ 17=c(mod 3233)
得到c = 2790
c^d=m(modn)
即2790 ^ 2753 = m(mod 3233)
得到m = 65
openssl是一个安全套接字层密码库,囊括主要的密码算法、常用密钥、证书封装管理功能及实现ssl协议。
openssl有三类命令:标准命令,消息摘要(dgst子命令),加密命令(enc子命令)
$openssl
OpenSSL> help
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
Message Digest commands (see the `dgst' command for more details)
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
Cipher commands (see the `enc' command for more details)
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 genrsa -out rsa_private.key 2048
通过该命令创建了pem编码的私钥
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA71qL1/8EPegW/LbtqhLs5N180IDK5KlqeA+xYo6rDKUYekLf
xRcjxDZbjQ3cEWIYSQ6aNBJPjh3KWPf6WjWBvk5WgxexXWGFOrzz5iaah+MPMAq2
iGqW8mdAszhHbD6FjP7OAH0kjsFTJVhmESXe9ngGxAxdooei+W1fp9W3DcYanRov
djh+1pvVpmBKdKpo3TVisgp9x5siUc3G236G8y8C0UWeyRjVpNfNrjtwtNAa08Xk
P4AJ+GAUP2N1bHARhe0YD3wkF779MnZY7QLsT5vXO8zcplxym90ZOAnKi9avpUrY
1/PIOI3yPwROTtn/BkQ9sNQDY1lcZX9/tgGfAQIDAQABAoIBAFYgQL3CN6aHAu6A
bFiMYs2fnS/xiBBrnbICA5QxPf9Y0Mv9kEN9JhOOc7b3y749i/uN05L1G8dJlOwa
nu0i38K4sYyOU/YEB0qxfxnLvkMzQt3InRHNOO+Uk8VpdNnQTYIEld+7KBJuIhsI
CgIVnHsXiWe2A2NeZxhVcNwVnL7JXdV83xsP3U7NDzETiraCT3XSqEGS3HeqPrSf
+9kGm3/txa6MdTNJ177X5WzB11ihptSVsMQ+w1j5vKZCY5kZwyhi9lzqhxWX6g9R
J1e3dg/NsD1l4qHhz6Hxb/qJWsdeHpCXiDFKGUYKP/N7n5UV1wJqOGAD6NowhoUB
ho2Oa/kCgYEA+sxNZD+vL2Cbkwy6aiI9M8QZ7Lm1637MSonrfb/pSd1CgWwFBlmb
146NZ6tVRIuTwNKgXyILJIuGK7Y1lxK6d9eDZf4pjm+mXbe0TCfD95pHvVuzivzt
l9bIzf/ij6mWbdtHEh3FmQGXphvwayKemgCu3YXgr0oFNYJxZg21MJcCgYEA9FF5
6icROF/Z8IHz6NqiHl1d6zWhpY74w4O5YENPXYnZbN/rr0HLxbHmkPMUVHliOORU
bH61GfhFQQKZpVd1VOBC2HoBcuUucl8VnDVxLUvg69XT+OLa5Wk/9Nn0UvQ35hgF
5T6jkn/whbJxc8kET8N1bfO2orGC3gc/Y9sBiCcCgYEAjfuHfM+I7/tzV+aGynsj
xuCoBJqGYRHhufkmtoQlIEoA0qBCn/uu/HOZni0jErEqLqmPXQw63q+Wf7yhzisu
IZaCrwUapaaTus67ZbnFebGAF7WIiZDzOVjBSc4ph0dtADh5ncn5Ccwa/FEo5J4u
x+THGmYmc1YmaMq2RB5Si3UCgYEA6YeTo9hR4nPkSrq8nL+WpLWUF0Z9S1W8vI2F
PNk53GvuMt5aVnvqvf4NKFHhBdm8pCrD86ytiLRB5iEJIfzV/xoZavg7uEoOOm5e
pqCCnMxhoqsR4V1d5FjVNEK9AinD4KDnybc0/Mxj6DensAfdoixva3jAAwTv1TBS
TC1DapMCgYAkFP7dV9HmfdXWPqsDoDgPsrC0ndqGhN0OodMax0+uaGkSaJLhEAWh
jTMNnyoMDiMlnRh9QTotAMnksu1xsdcFQckj3i8AzeSetseV4S/MlObcszDxPIam
neleAIEIa4Z5uao8Xjs2xyZi3nVL9bIozluz0UhGe+Zdixe4U7dieQ==
-----END RSA PRIVATE KEY-----
Rsa命令专门管理RSA密钥,从私钥中提取公钥等。
openssl rsa -in rsa_private.key -pubout -out rsa_public.pem
该命令从私钥文件中提取出公钥,默认也是pem编码,可以通过 -outform 参数,指定想导出的编码格式,如 DER、PEM、PVK
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA71qL1/8EPegW/LbtqhLs
5N180IDK5KlqeA+xYo6rDKUYekLfxRcjxDZbjQ3cEWIYSQ6aNBJPjh3KWPf6WjWB
vk5WgxexXWGFOrzz5iaah+MPMAq2iGqW8mdAszhHbD6FjP7OAH0kjsFTJVhmESXe
9ngGxAxdooei+W1fp9W3DcYanRovdjh+1pvVpmBKdKpo3TVisgp9x5siUc3G236G
8y8C0UWeyRjVpNfNrjtwtNAa08XkP4AJ+GAUP2N1bHARhe0YD3wkF779MnZY7QLs
T5vXO8zcplxym90ZOAnKi9avpUrY1/PIOI3yPwROTtn/BkQ9sNQDY1lcZX9/tgGf
AQIDAQAB
-----END PUBLIC KEY-----
根据私钥,生成对应的X509证书
openssl req -sha512 -new -x509 -key rsa_private.key -out rsatest.crt -days 3650 -subj /CN=jasonpang.com
证书从pem转换为der
openssl x509 -inform PEM -outform DER -text -in rsatest.crt -out rsatest.der
证书从pem转换为p7b
openssl crl2pkcs7 -nocrl -certfile rsatest.crt -out rsatest.p7b
#查看pem证书
openssl x509 -in rsatest.crt -noout -text
#查看p7b证书
openssl pkcs7 -print -in rsatest.p7b
根据RSA算法描述,我们知道公私钥需要有哪些核心数据。
那公私钥在文件中的格式是怎样的呢?
公钥的ASN.1格式
命令:openssl rsa -pubin -in rsa_public.key -noout -text
RSA Public-Key: (2048 bit)
Modulus:
00:ef:5a:8b:d7:ff:04:3d:e8:16:fc:b6:ed:aa:12:
ec:e4:dd:7c:d0:80:ca:e4:a9:6a:78:0f:b1:62:8e:
ab:0c:a5:18:7a:42:df:c5:17:23:c4:36:5b:8d:0d:
dc:11:62:18:49:0e:9a:34:12:4f:8e:1d:ca:58:f7:
fa:5a:35:81:be:4e:56:83:17:b1:5d:61:85:3a:bc:
f3:e6:26:9a:87:e3:0f:30:0a:b6:88:6a:96:f2:67:
40:b3:38:47:6c:3e:85:8c:fe:ce:00:7d:24:8e:c1:
53:25:58:66:11:25:de:f6:78:06:c4:0c:5d:a2:87:
a2:f9:6d:5f:a7:d5:b7:0d:c6:1a:9d:1a:2f:76:38:
7e:d6:9b:d5:a6:60:4a:74:aa:68:dd:35:62:b2:0a:
7d:c7:9b:22:51:cd:c6:db:7e:86:f3:2f:02:d1:45:
9e:c9:18:d5:a4:d7:cd:ae:3b:70:b4:d0:1a:d3:c5:
e4:3f:80:09:f8:60:14:3f:63:75:6c:70:11:85:ed:
18:0f:7c:24:17:be:fd:32:76:58:ed:02:ec:4f:9b:
d7:3b:cc:dc:a6:5c:72:9b:dd:19:38:09:ca:8b:d6:
af:a5:4a:d8:d7:f3:c8:38:8d:f2:3f:04:4e:4e:d9:
ff:06:44:3d:b0:d4:03:63:59:5c:65:7f:7f:b6:01:
9f:01
Exponent: 65537 (0x10001)
私钥的ASN.1格式
命令:openssl rsa -in rsa_private.key -noout -text
RSA Private-Key: (2048 bit, 2 primes)
modulus:
00:ef:5a:8b:d7:ff:04:3d:e8:16:fc:b6:ed:aa:12:
ec:e4:dd:7c:d0:80:ca:e4:a9:6a:78:0f:b1:62:8e:
ab:0c:a5:18:7a:42:df:c5:17:23:c4:36:5b:8d:0d:
dc:11:62:18:49:0e:9a:34:12:4f:8e:1d:ca:58:f7:
fa:5a:35:81:be:4e:56:83:17:b1:5d:61:85:3a:bc:
f3:e6:26:9a:87:e3:0f:30:0a:b6:88:6a:96:f2:67:
40:b3:38:47:6c:3e:85:8c:fe:ce:00:7d:24:8e:c1:
53:25:58:66:11:25:de:f6:78:06:c4:0c:5d:a2:87:
a2:f9:6d:5f:a7:d5:b7:0d:c6:1a:9d:1a:2f:76:38:
7e:d6:9b:d5:a6:60:4a:74:aa:68:dd:35:62:b2:0a:
7d:c7:9b:22:51:cd:c6:db:7e:86:f3:2f:02:d1:45:
9e:c9:18:d5:a4:d7:cd:ae:3b:70:b4:d0:1a:d3:c5:
e4:3f:80:09:f8:60:14:3f:63:75:6c:70:11:85:ed:
18:0f:7c:24:17:be:fd:32:76:58:ed:02:ec:4f:9b:
d7:3b:cc:dc:a6:5c:72:9b:dd:19:38:09:ca:8b:d6:
af:a5:4a:d8:d7:f3:c8:38:8d:f2:3f:04:4e:4e:d9:
ff:06:44:3d:b0:d4:03:63:59:5c:65:7f:7f:b6:01:
9f:01
publicExponent: 65537 (0x10001)
privateExponent:
56:20:40:bd:c2:37:a6:87:02:ee:80:6c:58:8c:62:
cd:9f:9d:2f:f1:88:10:6b:9d:b2:02:03:94:31:3d:
ff:58:d0:cb:fd:90:43:7d:26:13:8e:73:b6:f7:cb:
be:3d:8b:fb:8d:d3:92:f5:1b:c7:49:94:ec:1a:9e:
ed:22:df:c2:b8:b1:8c:8e:53:f6:04:07:4a:b1:7f:
19:cb:be:43:33:42:dd:c8:9d:11:cd:38:ef:94:93:
c5:69:74:d9:d0:4d:82:04:95:df:bb:28:12:6e:22:
1b:08:0a:02:15:9c:7b:17:89:67:b6:03:63:5e:67:
18:55:70:dc:15:9c:be:c9:5d:d5:7c:df:1b:0f:dd:
4e:cd:0f:31:13:8a:b6:82:4f:75:d2:a8:41:92:dc:
77:aa:3e:b4:9f:fb:d9:06:9b:7f:ed:c5:ae:8c:75:
33:49:d7:be:d7:e5:6c:c1:d7:58:a1:a6:d4:95:b0:
c4:3e:c3:58:f9:bc:a6:42:63:99:19:c3:28:62:f6:
5c:ea:87:15:97:ea:0f:51:27:57:b7:76:0f:cd:b0:
3d:65:e2:a1:e1:cf:a1:f1:6f:fa:89:5a:c7:5e:1e:
90:97:88:31:4a:19:46:0a:3f:f3:7b:9f:95:15:d7:
02:6a:38:60:03:e8:da:30:86:85:01:86:8d:8e:6b:
f9
prime1:
00:fa:cc:4d:64:3f:af:2f:60:9b:93:0c:ba:6a:22:
3d:33:c4:19:ec:b9:b5:eb:7e:cc:4a:89:eb:7d:bf:
e9:49:dd:42:81:6c:05:06:59:9b:d7:8e:8d:67:ab:
55:44:8b:93:c0:d2:a0:5f:22:0b:24:8b:86:2b:b6:
35:97:12:ba:77:d7:83:65:fe:29:8e:6f:a6:5d:b7:
b4:4c:27:c3:f7:9a:47:bd:5b:b3:8a:fc:ed:97:d6:
c8:cd:ff:e2:8f:a9:96:6d:db:47:12:1d:c5:99:01:
97:a6:1b:f0:6b:22:9e:9a:00:ae:dd:85:e0:af:4a:
05:35:82:71:66:0d:b5:30:97
prime2:
00:f4:51:79:ea:27:11:38:5f:d9:f0:81:f3:e8:da:
a2:1e:5d:5d:eb:35:a1:a5:8e:f8:c3:83:b9:60:43:
4f:5d:89:d9:6c:df:eb:af:41:cb:c5:b1:e6:90:f3:
14:54:79:62:38:e4:54:6c:7e:b5:19:f8:45:41:02:
99:a5:57:75:54:e0:42:d8:7a:01:72:e5:2e:72:5f:
15:9c:35:71:2d:4b:e0:eb:d5:d3:f8:e2:da:e5:69:
3f:f4:d9:f4:52:f4:37:e6:18:05:e5:3e:a3:92:7f:
f0:85:b2:71:73:c9:04:4f:c3:75:6d:f3:b6:a2:b1:
82:de:07:3f:63:db:01:88:27
exponent1:
00:8d:fb:87:7c:cf:88:ef:fb:73:57:e6:86:ca:7b:
23:c6:e0:a8:04:9a:86:61:11:e1:b9:f9:26:b6:84:
25:20:4a:00:d2:a0:42:9f:fb:ae:fc:73:99:9e:2d:
23:12:b1:2a:2e:a9:8f:5d:0c:3a:de:af:96:7f:bc:
a1:ce:2b:2e:21:96:82:af:05:1a:a5:a6:93:ba:ce:
bb:65:b9:c5:79:b1:80:17:b5:88:89:90:f3:39:58:
c1:49:ce:29:87:47:6d:00:38:79:9d:c9:f9:09:cc:
1a:fc:51:28:e4:9e:2e:c7:e4:c7:1a:66:26:73:56:
26:68:ca:b6:44:1e:52:8b:75
exponent2:
00:e9:87:93:a3:d8:51:e2:73:e4:4a:ba:bc:9c:bf:
96:a4:b5:94:17:46:7d:4b:55:bc:bc:8d:85:3c:d9:
39:dc:6b:ee:32:de:5a:56:7b:ea:bd:fe:0d:28:51:
e1:05:d9:bc:a4:2a:c3:f3:ac:ad:88:b4:41:e6:21:
09:21:fc:d5:ff:1a:19:6a:f8:3b:b8:4a:0e:3a:6e:
5e:a6:a0:82:9c:cc:61:a2:ab:11:e1:5d:5d:e4:58:
d5:34:42:bd:02:29:c3:e0:a0:e7:c9:b7:34:fc:cc:
63:e8:37:a7:b0:07:dd:a2:2c:6f:6b:78:c0:03:04:
ef:d5:30:52:4c:2d:43:6a:93
coefficient:
24:14:fe:dd:57:d1:e6:7d:d5:d6:3e:ab:03:a0:38:
0f:b2:b0:b4:9d:da:86:84:dd:0e:a1:d3:1a:c7:4f:
ae:68:69:12:68:92:e1:10:05:a1:8d:33:0d:9f:2a:
0c:0e:23:25:9d:18:7d:41:3a:2d:00:c9:e4:b2:ed:
71:b1:d7:05:41:c9:23:de:2f:00:cd:e4:9e:b6:c7:
95:e1:2f:cc:94:e6:dc:b3:30:f1:3c:86:a6:9d:e9:
5e:00:81:08:6b:86:79:b9:aa:3c:5e:3b:36:c7:26:
62:de:75:4b:f5:b2:28:ce:5b:b3:d1:48:46:7b:e6:
5d:8b:17:b8:53:b7:62:79
X.509数字证书用ASN.1描述如下:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate, -- 证书内容(待签名),包含持有者公钥、持有者信息、签发者信息
signatureAlgorithm AlgorithmIdentifier, -- 签名算法,包括摘要算法和公钥算法,如sha1WithRSAEncryption,由算法标识和算法参数组成
signature BIT STRING -- 使用签名算法对证书内容tbsCertificate进行签名后的结果
}
AlgorithmIdentifier ::= SEQUENCE {
Algorithm OBJECT IDENTIFIER,
Parameters ANY DEFINED BY algorithm OPTIONAL}
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1, --版本号,用于区分证书格式版本,最新版本V3,缺省值为V1
serialNumber CertificateSerialNumber, -- 序列号,证书唯一标识,由签发者统一分配
signature AlgorithmIdentifier, --签名算法,必须与证书域中的签名算法相同,即等于Certificate->signatureAlgorithm
issuer Name, -- 用于区分证书签发者,包含证书签发者身份信息
validity Validity, -- 由生效日期和失效日期组成
subject Name, -- 用于区分证书持有者,包含证书持有者身份信息
subjectPublicKeyInfo SubjectPublicKeyInfo, -- 包含证书持有者公钥信息
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, --表示证书签发者唯一标识
-- If present, version must be v2or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, --表示证书持有者唯一标识
-- If present, version must be v2or v3
extensions [3] EXPLICIT Extensions OPTIONAL --包含其他可扩展信息
-- If present, version must be v3
}
Version ::= INTEGER {
v1(0), v2(1), v3(2)
}
CertificateSerialNumber ::= INTEGER --序列号必须是正整数
Validity ::= SEQUENCE {
notBefore CertificateValidityDate,
notAfter CertificateValidityDate
}
CertificateValidityDate ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime
}
UniqueIdentifier ::= BIT STRING
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING
}
Extensions ::= SEQUENCE OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING
}
我们可以使用mac的钥匙串查看openssl生成的证书信息
公共秘钥与指数:大家可以看到,这两个信息,正是公钥文件里的n和e
指纹:
纹指纹不是证书的签名值, 和证书本身生成的字段无关, 并不包含在证书中. 因为你的任何改动都会影响最终输出的DER或PEM文件, 所以只能在证书生成之后进行指纹生成.
计算:要计算指纹,首先需要将其从PEM表示解码为二进制。为此,需要删除页眉和页脚(从-----
开始),其余部分需要解码为base64。从得到的二进制文件中,可以计算SHA1或SHA-256散列。
grep -v ^- rsatest.crt | base64 -d | sha256sum
结果为c455ce81fd0ce98eb70bc59f10f099f4ca9cd04ccd0eda4cce29ead2fcb72323,和图片信息一致
签名过程:CA机构拥有非对称加密的私钥和公钥。CA机构对证书明文数据T进行hash。对hash后的值用私钥加密,得到数字签名S。明文和数字签名共同组成了数字证书。
验证过程:拿到证书,得到明文T,签名S。用CA机构的公钥对S解密(由于是浏览器信任的机构,所以浏览器保有它的公钥。详情见下文),得到S’。用证书里指明的hash算法对明文T进行hash得到T’。显然通过以上步骤,T’应当等于S‘,除非明文或签名被篡改。所以此时比较S’是否等于T’,等于则表明证书可信。
明文数据T:TBSCertificate结构的der编码是计算签名的数据
这个证书是根证书,所以自己给自己进行签名
大家是否被众多的证书格式搞懵了?让我们看一下证书和私钥都以哪些形式进行保存!图片来自 https://www.processon.com/view/link/63c8f6ffc12afe0cada9b596
我们找几个常用的编码格式,看看它们的真实样子。
PEM是把二进制数据通过Base64进行编码,然后在头部添加header -----BEGIN XXX----- 尾部添加footer -----END XXX-----。 header 和footer之间的数据就是被Base64编码的二进制数据。XXX 是要编码的数据内容类型,可以是 CERTIFICATE 、CERTIFICATE REQUEST、 PRIVATE KEY 、X509 CRL 。
上述的公钥、私钥、证书都是pem编码,可以看到都带有-----BEGIN XXX-----。
Base64是一种很常用的编码方式,可以将任意二进制字节编码成64个可打印的ASCII码字符。Base64编码的基本原理如下。
1.字符索引
64个字符包括大小写英文字母各26个、10个数字、加号和左斜杠。等号用于末尾填充。64个字符所对应的索引如表所示。
将二进制字节流按3个字节一组进行分组,然后分别对每个3字节组进行编码。当二进制字节流长度不是3的倍
数时,最后一个3字节组可能不足3个字节,编码时需要进行填充处理。每个3字节组可编码成4个字符。
将3字节组中的每个字节按最高位到最低位顺序排列后组成24位,然后按6位一组分成4组,每组取值范围为0
~63,将每组取值作为索引按照表5-7获得对应的字符后,最终形成4个字符。
如果最后的3字节组只有1个字节,则将形成8位,右边补足4位0比特后,可形成2个6位组,转换成2个字符,
然后填充2个等号,凑成4个字符。如果最后的3字节组只有2个字节,将形成16位,右边补足2位0比特后,可
形成3个6位组,转换成3个字符,然后填充1个等号,凑成4个字符。
Base64编码后的字符之间允许插入回车换行符,但每行不允许超过76个字个字符。
3.解码过程
将字符流中回车换行符删除后,按 4 个字符一组进行分组,然后分别对每个 4 字符组进行解码。若删除回车换
行符后的字符流长度不是4的倍数,则该字符流有误。每个4字符组可解码成 3个字节。若最后一个 4字符组末
尾是 1或 2个等号,将解码成 2或 1个字节。
将 4 字符组中每个字符按表 5-8 获得对应的索引,该索引取值范围为 0~63,将索引转换成6位比特后,按最
高位到最低位顺序排列后组成24位比特;然后按8位一组分成3组,每组8位转换成1个字节,最终形成3个字
节。
如果最后的4字符组末尾是1个等号,则前3个字符的索引将组合成18位,取前16位转换成2个字节。如果最后
的4字符组末尾是2个等号,则前2个字符的索引将组合成12位,取前8位比特转换成1个字符。
将X509证书从PEM格式转换为DER格式
openssl x509 -inform PEM -outform DER -text -in rsatest.crt -out rsatest.der
cat rsatest.der
能够看到证书的信息,同时还有部分乱码
openssl crl2pkcs7 -nocrl -certfile rsatest.crt -out rsatest.p7b
cat rsatest.p7b
结果为:
-----BEGIN PKCS7-----
MIIDQAYJKoZIhvcNAQcCoIIDMTCCAy0CAQExADALBgkqhkiG9w0BBwGgggMVMIID
ETCCAfmgAwIBAgIULycC2Tf/y7um8/WhJrWy/naloJQwDQYJKoZIhvcNAQENBQAw
GDEWMBQGA1UEAwwNamFzb25wYW5nLmNvbTAeFw0yMzAxMTkwMjUxMzdaFw0zMzAx
MTYwMjUxMzdaMBgxFjAUBgNVBAMMDWphc29ucGFuZy5jb20wggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDvWovX/wQ96Bb8tu2qEuzk3XzQgMrkqWp4D7Fi
jqsMpRh6Qt/FFyPENluNDdwRYhhJDpo0Ek+OHcpY9/paNYG+TlaDF7FdYYU6vPPm
JpqH4w8wCraIapbyZ0CzOEdsPoWM/s4AfSSOwVMlWGYRJd72eAbEDF2ih6L5bV+n
1bcNxhqdGi92OH7Wm9WmYEp0qmjdNWKyCn3HmyJRzcbbfobzLwLRRZ7JGNWk182u
O3C00BrTxeQ/gAn4YBQ/Y3VscBGF7RgPfCQXvv0ydljtAuxPm9c7zNymXHKb3Rk4
CcqL1q+lStjX88g4jfI/BE5O2f8GRD2w1ANjWVxlf3+2AZ8BAgMBAAGjUzBRMB0G
A1UdDgQWBBSCjbFdXy7jx6jYo0f/6n1k63c3vzAfBgNVHSMEGDAWgBSCjbFdXy7j
x6jYo0f/6n1k63c3vzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IB
AQBem1lBhTmCF9Z996XF8VlOiDk+sQSd6L878Kxrp9DvWA7+8EE3GFewLkPtk7hf
yTDTXBbyHom3dIfhBlcB5YFB8aJkpnIJUnWnRkXpHi/q95zcEzLPH+LvSsLkhTHU
g8Npdmzn4wF3tU+JFrnzQumV1uU6It9JPJtjgr91Tr+x1VKMOTnelDEP+rk/pFPS
SmllrXxqCRg+dWlIibdxMZr4AHP8a3vbqewp9gKcf21VQxVy8Nlj35o+WVh6M37O
Tt335wxw2vYI8TnjejtGpqq1b2Vd7SsXE28e4EfVpOtowhQW12VEFct/Tka0LEex
Fp157eoxEGVft3k45t6KZWJ+MQA=
-----END PKCS7----
通过如下命令可查看p7b格式
openssl pkcs7 -print -in rsatest.p7b
终于梳理完RSA和证书之间的关系。
RSA生成公私钥,其中公钥制成证书。公私钥、证书的格式、细节也都做了说明。希望对大家有所帮助。
这部分内容可以和这两篇文章一起看:
常用密码算法介绍
来了解一下ASN.1?
大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)
我的个人博客为:https://shidawuhen.github.io/
往期文章回顾: