RSA与证书

这篇文章详细讲述一下RSA与证书的相关内容。内容有点多,但都是干货。

一、RSA算法

1.1简介

RSA算法是由美国三位科学家Rivest、Shamir和Adleman于1976年提出并在1978年正式发表的公开密码算

法,其命名取自三位创始人名字的首字母缩写。该算法基于数论中的大数分解难题,即:根据数论,寻求两个

大素数比较简单,而将它们的乘积分解开则极其困难。

1.2算法说明

该算法中,用户有两个密钥:公钥 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),则加密和解密运算为:

screenshot-20230118-102630.png
(2)密钥的产生

① 计算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互素的数的

个数。

  • 在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目。
  • 互质/互素是公约数只有1的两个整数,叫做互质整数。公约数只有1的两个自然数,叫做互质自然数,后者是前者的特殊情形。

③ 选择e。用户从[0,φ(n)-1]中选择一个与φ(n)互素的数e作为公开的加密指数。

④ 计算d。用户计算出满足公式ed=1 modφ(n)的d作为解密指数。

⑤ 得出所需要的公钥和私钥:

screenshot-20230118-102702.png

1.3实际运算

1.3.1公私钥值

实际走一下计算过程

  1. 随机选择两个不相等的质数p和q,p = 61,q = 53

  2. 计算p和q的乘积n,n = 61×53 = 3233

  3. 计算n的欧拉函数φ(n)(这儿用到了欧拉定理)

  • φ(n) = (p1-1)(p2-1)

  • φ(3233) = 60x52 = 3120

  1. 随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质 ,假设选择了17

  2. 计算出d,使得ed % φ(n)=(17*2753)%3120 = 1(如何解出d需要用到辗转相除法),得到d为2753

  3. 形成公钥(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
}

1.3.2加解密

用公钥加密,假设选择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

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           

2.1创建私钥

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-----

2.2获取公钥

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-----

2.3生成证书

根据私钥,生成对应的X509证书

openssl req -sha512 -new -x509 -key rsa_private.key -out rsatest.crt -days 3650 -subj /CN=jasonpang.com

2.4证书格式转换

证书从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

2.5查看证书

#查看pem证书
openssl x509 -in rsatest.crt -noout -text
#查看p7b证书
openssl pkcs7 -print -in rsatest.p7b

三、公私钥格式说明

根据RSA算法描述,我们知道公私钥需要有哪些核心数据。

screenshot-20230118-102702.png

那公私钥在文件中的格式是怎样的呢?

3.1公钥格式

公钥的ASN.1格式

RSA与证书_第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)

3.2私钥格式

私钥的ASN.1格式

RSA与证书_第2张图片

命令: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

3.3说明

  1. e的值为65537原因
  • NIST SP800-78 Rev 1 (2007) 曾强调“不允许使用比65537更低的公钥指数e”,但PKCS#1却从未有过类似的建议。e=65537=(2^16+1),其签名/加密运算只需要17次模乘,性能也算不错。但我认为选这个值的目的只是一个介于小指数攻击和运算效率之间的一个折中考虑,即以防万一将来有一天"e=3"被攻破而侥幸"e=65537"可能还是安全的。
  1. 公钥需要包含e、n,私钥需要d、n
  • 私钥文件里面包含n、e、d、p、q等,所以可以从私钥文件获取到公钥
  • 如果有n、e、d、p、q,也可自行制作出公私钥文件
  • 公钥、私钥不是只有一个数值,而是由多个数值的组合而成
  1. https://www.gmssl.cn/gmssl/index.jsp 可查看公私钥文件里的数值

RSA与证书_第3张图片

四、数字证书

4.1证书格式

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
  }

4.2查看证书

4.2.1细节

我们可以使用mac的钥匙串查看openssl生成的证书信息

RSA与证书_第4张图片

4.2.2说明

  1. 公共秘钥与指数:大家可以看到,这两个信息,正是公钥文件里的n和e

  2. 指纹:

  • 纹指纹不是证书的签名值, 和证书本身生成的字段无关, 并不包含在证书中. 因为你的任何改动都会影响最终输出的DER或PEM文件, 所以只能在证书生成之后进行指纹生成.

  • 计算:要计算指纹,首先需要将其从PEM表示解码为二进制。为此,需要删除页眉和页脚(从-----开始),其余部分需要解码为base64。从得到的二进制文件中,可以计算SHA1或SHA-256散列。

grep -v ^- rsatest.crt  | base64 -d | sha256sum 

​ 结果为c455ce81fd0ce98eb70bc59f10f099f4ca9cd04ccd0eda4cce29ead2fcb72323,和图片信息一致

  1. 签名
  • 签名过程: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

RSA与证书_第5张图片

我们找几个常用的编码格式,看看它们的真实样子。

5.1pem编码

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个字符所对应的索引如表所示。

RSA与证书_第6张图片
2.编码过程

将二进制字节流按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个字符。

5.2der编码

将X509证书从PEM格式转换为DER格式

openssl x509 -inform PEM -outform DER -text -in rsatest.crt -out rsatest.der
cat rsatest.der

能够看到证书的信息,同时还有部分乱码

RSA与证书_第7张图片

5.3p7b编码

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与证书_第8张图片

六、总结

终于梳理完RSA和证书之间的关系。

RSA生成公私钥,其中公钥制成证书。公私钥、证书的格式、细节也都做了说明。希望对大家有所帮助。

这部分内容可以和这两篇文章一起看:

常用密码算法介绍

来了解一下ASN.1?

七、资料

  1. X509证书及其格式扩展名
  2. https://www.icode9.com/content-4-613610.html
  3. https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
  4. https://zh.m.wikipedia.org/zh-hans/X.509
  5. https://tech.bytedance.net/articles/7094078786773188639#doxcnAC0w2kWkwS8ui6Bajy5GUf
  6. 搞懂 PEM、ANS、PFX、P12、p8、CER、X509 等证书相关文件格式 后缀
  7. 国密实验室
  8. PHP实现DER密钥转PEM密钥
  9. pem 文件详解
  10. OpenSSL简介
  11. RSA 从私钥中获取公钥
  12. 素数/质数
  13. 欧拉函数
  14. 互质/互素
  15. RSA算法计算过程
  16. 欧拉函数及其计算
  17. C语言实现欧拉函数的计算
  18. 进制转换
  19. Java从RSA私钥中提取出 E N P Q D DP DQ QP
  20. RSA——长度问题
  21. RSA2048基础知识
  22. 使用OpenSSL从bash中的n,e,d,p,q值生成RSA私钥
  23. 为什么RSA 公钥指数(e=65537)
  24. 利用openssl生成X509证书
  25. RSA.SignHash SHA512 和 SHA256 给出相同的签名长度
  26. 如何正确计算证书的指纹
  27. 关于证书指纹
  28. 解释X509数字证书的证书签名值字段
  29. 数字签名、数字证书与CA
  30. 数字证书和数字签名
  31. 证书链的终极版
  32. 使用openssl进行证书格式转换
  33. openssl ans.1编码规则分析及证书密钥编码方式

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

  1. 设计模式
  2. 招聘
  3. 思考
  4. 存储
  5. 算法系列
  6. 读书笔记
  7. 小工具
  8. 架构
  9. 网络
  10. Go语言

你可能感兴趣的:(架构,算法,后端)