以bing.com 为例
1. CA 层级的基本概念
CA 层级是一种树状结构,由多个层级的 CA 组成。每个 CA 负责为其下一层级的实体(如子 CA 或终端实体)颁发证书。层级结构的顶端是 根 CA(Root CA),它是整个 PKI 体系的信任锚点。
主要角色
-
根 CA(Root CA):
-
位于层级结构的顶端。
-
自签名证书(自己为自己颁发证书)。
-
是信任链的起点。
-
-
中间 CA(Intermediate CA):
-
位于根 CA 和终端实体之间。
-
由根 CA 或上级中间 CA 颁发证书。
-
负责为终端实体或其他中间 CA 颁发证书。
-
-
终端实体(End Entity):
-
层级结构的最底层。
-
包括用户、设备、服务器等。
-
证书由中间 CA 颁发。
-
可以从中间ca获取公钥
模数(4096 位):
B2 EE 82 05 CD C0 D5 65 56 E8 99 66 6D 4B 0A C0
5F C2 E2 29 7B 1B 09 CC 2E 14 BE C5 1E 40 F9 9B
AE E8 96 63 9D 4E E7 8E 2A 13 44 47 9C A4 16 CF
E6 78 A1 B5 7F 0C DD DF 9F FE 43 5F 8A 4F 17 15
F3 D2 08 5E 61 2B B5 2B 23 F0 45 AE EE B7 44 01
56 27 60 C1 5B B2 DA B0 90 85 4D 12 8C F8 38 83
3C DA 19 FE 37 9A 79 EF 39 07 18 FA 20 CC 5E 93
38 F4 54 38 AF 32 63 20 8F 7A A9 C7 BE 85 69 13
96 F4 91 92 F8 41 3F 1B 77 28 52 45 06 D4 B1 48
92 68 EB 85 E7 2D DE 67 D5 5C F7 66 DA 0E 48 58
EC 21 59 13 64 E1 2C BB F9 3D 0D 16 C7 32 E8 B7
7B 75 F1 DD AF 40 FE 71 DB D2 34 9F A3 45 B2 3D
FB 27 67 7F 10 7F D9 E9 AF E5 84 05 73 2A 37 D8
96 81 9C 43 52 0F C8 31 08 1A 1F 60 60 99 CC 2C
56 62 51 B9 BF 18 19 A5 A4 A5 6B F0 CD 37 39 62
82 47 4B 61 45 B7 E7 53 A5 28 B2 4A F0 1A B1 02
02 79 E8 8C 51 14 C3 E8 FC 8B A8 05 2C 13 56 5E
D0 4E B5 8B E0 97 C4 87 08 25 4A 51 45 25 E1 83
9F 47 9C C5 E0 E9 0A 8A B2 6E 51 B3 A6 07 60 0E
98 B8 D8 24 87 1A 6C 3B F1 31 C9 AB CA 14 22 9E
88 3E FF E8 E0 1C 99 D8 EB 6A 29 81 2B 64 75 A2
26 30 FC F2 2C 1E D9 69 65 67 C6 94 5D B4 52 8E
D5 9B C6 91 97 91 36 F6 CF 01 42 91 DA 43 5E 92
7B A1 DC DB 45 BF 3D 9D 63 7C 4F EC 07 E1 C8 B1
3F B7 CB D6 EF 69 C0 CE 54 4A CF EF 8B EF 40 A0
0A F8 FF C9 E3 9B 3F 06 80 3C 37 76 B1 9D 28 8F
6B BF 37 E9 3A 7A 01 AA D3 87 BE 18 15 BE 41 80
92 A0 9E 5E 01 8D FA 8A 5D 1F BB B7 58 48 76 03
A3 B4 41 E5 A3 D3 2E A9 F2 6E 9F 30 31 E0 1A B5
C6 A0 73 C5 3D 38 CE 36 82 11 0B 4D A5 85 01 1B
B2 A0 29 A0 A9 1E F2 F1 F0 14 F4 D8 E1 72 AA E6
EB ED 17 CE FF EF CC C7 E1 2F 85 25 A5 FD 46 EF
公用指数(17 位):
01 00 01
使用上述公钥,验签对应私钥签名(使用 RSA 加密的 PKCS #1 SHA-384)
签名值如上上图红色部分。
import hashlib
sign='''97 2B 9D FA E4 55 B2 67 12 26 C5 A7 05 1C 0C 52
13 EC 0E 18 C5 83 40 5D 38 61 33 65 18 8F 23 7B
D5 1C 7D E9 EF 5D D2 15 AD 02 5F 37 2A 35 24 C2
56 FD 71 46 08 2F 31 98 24 59 2E F2 89 46 40 EA
04 3D CF 8F 3A 68 F7 4B 7B 3D 19 70 56 83 A1 D3
BA 07 45 C1 C6 8A 1F 20 20 13 47 A6 DB F0 9F F3
B2 D6 49 37 8A 20 DC 57 88 21 F4 46 16 70 7D 8B
C4 3B 69 B5 63 01 13 68 62 2A DA CC 02 E2 F7 E3
FC 1D 1D 03 30 EC AD D3 6F 7D 47 A4 E3 AA 3A 98
9C D3 28 94 3A 7E 6D 38 80 04 F2 D5 14 F9 DC C4
6A B4 15 DB 0E 5E CE 2E D3 95 94 72 43 E8 27 B7
E2 2B F8 3C 82 F9 30 5F F4 2A 0E B9 0C E9 15 FE
20 94 F0 E5 B7 95 58 2C 78 BE 2A 58 2C 75 96 C0
43 66 F8 07 C6 11 D0 7F B1 17 9F DE 4D 10 E0 A6
BB 78 FE 6F 5B 93 AE 69 9A 3B 7A F5 ED DA 39 15
0F 3C F8 C4 24 EA 8A 76 53 80 E2 9E 58 E4 4F 84
2E C3 AA BF 75 48 98 BC 6A 67 73 A5 DB 14 87 27
29 5A 83 D9 77 3B 82 1C 2E 6D 65 AF 45 96 88 75
AB 15 A5 3A A3 47 01 12 85 5A 3C 45 3B 60 D4 3A
95 09 85 F0 D9 17 8D 57 77 E0 A7 7C AD BF 7E 97
86 9D 10 D3 C7 23 3A 40 7D E0 78 F0 CB 4B 28 CD
93 2F 2E B7 D0 49 05 1C F5 8E 17 32 28 05 F9 FA
FD 03 A7 E1 3F A1 B5 8C BD 13 A0 C2 FA E6 D7 45
96 BC 7D C9 3F AE 52 96 DF 93 9D CC A3 52 C6 77
F9 B0 1F E5 9D 7E AE 2A B2 F4 DB 8A 13 F6 FF E9
34 93 B1 C7 6D 4E 14 40 9A 70 EF 1D AA 4C 3D E2
FC 7E FA 5C D2 FE EB 49 69 0D 1A 81 08 61 E6 DC
6D 98 06 8E A6 51 05 BD 1F 17 D7 09 53 43 03 CF
9B 72 62 77 7E DF 8B 0C 24 1B 78 CF 4B 3E D4 42
C9 46 CE DF 3A 53 3F 95 96 19 46 07 06 97 4F C7
92 FD 14 A6 2F C4 41 62 BA 37 D2 EB 51 62 60 05
E2 59 8B E3 7F 5E 6B AF 32 72 4F 00 B2 81 69 70'''
sign=sign.replace('\n','').replace(' ','')
sign=int(sign,16)
e=0x10001
public_n='''B2 EE 82 05 CD C0 D5 65 56 E8 99 66 6D 4B 0A C0
5F C2 E2 29 7B 1B 09 CC 2E 14 BE C5 1E 40 F9 9B
AE E8 96 63 9D 4E E7 8E 2A 13 44 47 9C A4 16 CF
E6 78 A1 B5 7F 0C DD DF 9F FE 43 5F 8A 4F 17 15
F3 D2 08 5E 61 2B B5 2B 23 F0 45 AE EE B7 44 01
56 27 60 C1 5B B2 DA B0 90 85 4D 12 8C F8 38 83
3C DA 19 FE 37 9A 79 EF 39 07 18 FA 20 CC 5E 93
38 F4 54 38 AF 32 63 20 8F 7A A9 C7 BE 85 69 13
96 F4 91 92 F8 41 3F 1B 77 28 52 45 06 D4 B1 48
92 68 EB 85 E7 2D DE 67 D5 5C F7 66 DA 0E 48 58
EC 21 59 13 64 E1 2C BB F9 3D 0D 16 C7 32 E8 B7
7B 75 F1 DD AF 40 FE 71 DB D2 34 9F A3 45 B2 3D
FB 27 67 7F 10 7F D9 E9 AF E5 84 05 73 2A 37 D8
96 81 9C 43 52 0F C8 31 08 1A 1F 60 60 99 CC 2C
56 62 51 B9 BF 18 19 A5 A4 A5 6B F0 CD 37 39 62
82 47 4B 61 45 B7 E7 53 A5 28 B2 4A F0 1A B1 02
02 79 E8 8C 51 14 C3 E8 FC 8B A8 05 2C 13 56 5E
D0 4E B5 8B E0 97 C4 87 08 25 4A 51 45 25 E1 83
9F 47 9C C5 E0 E9 0A 8A B2 6E 51 B3 A6 07 60 0E
98 B8 D8 24 87 1A 6C 3B F1 31 C9 AB CA 14 22 9E
88 3E FF E8 E0 1C 99 D8 EB 6A 29 81 2B 64 75 A2
26 30 FC F2 2C 1E D9 69 65 67 C6 94 5D B4 52 8E
D5 9B C6 91 97 91 36 F6 CF 01 42 91 DA 43 5E 92
7B A1 DC DB 45 BF 3D 9D 63 7C 4F EC 07 E1 C8 B1
3F B7 CB D6 EF 69 C0 CE 54 4A CF EF 8B EF 40 A0
0A F8 FF C9 E3 9B 3F 06 80 3C 37 76 B1 9D 28 8F
6B BF 37 E9 3A 7A 01 AA D3 87 BE 18 15 BE 41 80
92 A0 9E 5E 01 8D FA 8A 5D 1F BB B7 58 48 76 03
A3 B4 41 E5 A3 D3 2E A9 F2 6E 9F 30 31 E0 1A B5
C6 A0 73 C5 3D 38 CE 36 82 11 0B 4D A5 85 01 1B
B2 A0 29 A0 A9 1E F2 F1 F0 14 F4 D8 E1 72 AA E6
EB ED 17 CE FF EF CC C7 E1 2F 85 25 A5 FD 46 EF'''
public_n=public_n.replace('\n','').replace(' ','')
public_n=int(public_n,16)
m=pow(sign,e,public_n)
print(hex(m))
# 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430f0b5b67540085f352c9652c17655ece83bedc6ac86e490bbda003123f08d28ae5087e389f1dcf978e96c282d755bb5b6
如果解出来是0x1fffffff格式,应该是解对了,貌似PKCS #1的填充格式就是这样的。
RFC 8017: PKCS #1: RSA Cryptography Specifications Version 2.2
基于以上格式可以提取出证书的hash值。
sha384='f0b5b67540085f352c9652c17655ece83bedc6ac86e490bbda003123f08d28ae5087e389f1dcf978e96c282d755bb5b6'
接下来手动计算证书的hash是否和我们提取的sha384相等。
先导出证书
base64编码的ascii ,单个证书长这个样子
-----BEGIN CERTIFICATE-----
MIINWTCCC0GgAwIBAgITMwD36wOscXLGFiN8dwAAAPfrAzANBgkqhkiG9w0BAQwF
ADBdMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
MS4wLAYDVQQDEyVNaWNyb3NvZnQgQXp1cmUgUlNBIFRMUyBJc3N1aW5nIENBIDA4
MB4XDTI0MTIxNTA3NTIyOFoXDTI1MDYxMzA3NTIyOFowYzELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAldBMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
ZnQgQ29ycG9yYXRpb24xFTATBgNVBAMTDHd3dy5iaW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAKOE2PRzy3AhT9TJGbN/JYTKDu5Asz7uUdFk
nrLrXIEmmpn57QuVxuLVUgPkz/W8w5jaPHyHlzeqEP1ajswS1o+cxqiYBcFTWhfS
z7A6HIY3UzafEjhwM6EMibKro/H4Tkpb8QHz0iIeic4nPaIsXl3mM1YoSuR/f83k
rQunifp7qUpkwmbj0OUVY1j0HPwc4TLHFk8sAAUtH8nq9B7oXT6jhEVE2dQPGavh
bBkwV9vCdxpZgxdFpe1I+N+Nqma3U4vo8AMouGKsJ1Ir9AaNudDM2p3x6Q4mbr20
mmij8ld/X1Icpneoa29MO2I4ebqkreSf+UA+8Gp+t7TnhsKXCokCAwEAAaOCCQow
ggkGMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgDPEVbu1S58r/OHW9lpLpvp
GnFnSrAX7KwB0lt3zsw7CAAAAZPJVyTUAAAEAwBHMEUCIBFsWqv3SCYOeAbgn7O9
fXE31BM945CB+ryCnPpmQJi4AiEAmb8uqZVavqrUfY8uDEkRIFulCbHBaj8VSWS0
crp0lIEAdgB9WR4S4XgqexxhZ3xe/fjQh1wUoE6VnrkDL9kOjC55uAAAAZPJVyUT
AAAEAwBHMEUCIQCtGjV3pIPRT0JZU6Qa9s1UaYoei+aO1iq148Wq1ZrG5wIgKvVe
9fj5dr/JhHruW9gRCAi2J5rIQGbbSLh1ZFCzeHkAdgDgkrP8DB3I52g2H95huZZN
ClJ4GYpy1nLEsE2lbW9UBAAAAZPJVyUnAAAEAwBHMEUCIHrzZn/f8fgibS2d+JSq
rNHTdZTOdjrX8M22GcaG4akcAiEA7PzDwesXuDwRj/QAzxPfAEZrkOmurLr6mnhg
2ID13kIwJwYJKwYBBAGCNxUKBBowGDAKBggrBgEFBQcDAjAKBggrBgEFBQcDATA8
BgkrBgEEAYI3FQcELzAtBiUrBgEEAYI3FQiHvdcbgefrRoKBnS6O0AyH8NodXYKr
5zCH7fEfAgFkAgEtMIG0BggrBgEFBQcBAQSBpzCBpDBzBggrBgEFBQcwAoZnaHR0
cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBB
enVyZSUyMFJTQSUyMFRMUyUyMElzc3VpbmclMjBDQSUyMDA4JTIwLSUyMHhzaWdu
LmNydDAtBggrBgEFBQcwAYYhaHR0cDovL29uZW9jc3AubWljcm9zb2Z0LmNvbS9v
Y3NwMB0GA1UdDgQWBBSdG38i9dxNEO6vPvTS31L/30wD5jAOBgNVHQ8BAf8EBAMC
BaAwggURBgNVHREEggUIMIIFBIITKi5wbGF0Zm9ybS5iaW5nLmNvbYIKKi5iaW5n
LmNvbYIIYmluZy5jb22CFmllb25saW5lLm1pY3Jvc29mdC5jb22CEyoud2luZG93
c3NlYXJjaC5jb22CGWNuLmllb25saW5lLm1pY3Jvc29mdC5jb22CESoub3JpZ2lu
LmJpbmcuY29tgg0qLm1tLmJpbmcubmV0gg4qLmFwaS5iaW5nLmNvbYINKi5jbi5i
aW5nLm5ldIINKi5jbi5iaW5nLmNvbYIQc3NsLWFwaS5iaW5nLmNvbYIQc3NsLWFw
aS5iaW5nLm5ldIIOKi5hcGkuYmluZy5uZXSCDiouYmluZ2FwaXMuY29tgg9iaW5n
c2FuZGJveC5jb22CFmZlZWRiYWNrLm1pY3Jvc29mdC5jb22CG2luc2VydG1lZGlh
LmJpbmcub2ZmaWNlLm5ldIIOci5iYXQuYmluZy5jb22CECouci5iYXQuYmluZy5j
b22CDyouZGljdC5iaW5nLmNvbYIOKi5zc2wuYmluZy5jb22CECouYXBwZXguYmlu
Zy5jb22CFioucGxhdGZvcm0uY24uYmluZy5jb22CDXdwLm0uYmluZy5jb22CDCou
bS5iaW5nLmNvbYIPZ2xvYmFsLmJpbmcuY29tghF3aW5kb3dzc2VhcmNoLmNvbYIO
c2VhcmNoLm1zbi5jb22CESouYmluZ3NhbmRib3guY29tghkqLmFwaS50aWxlcy5k
aXR1LmxpdmUuY29tghgqLnQwLnRpbGVzLmRpdHUubGl2ZS5jb22CGCoudDEudGls
ZXMuZGl0dS5saXZlLmNvbYIYKi50Mi50aWxlcy5kaXR1LmxpdmUuY29tghgqLnQz
LnRpbGVzLmRpdHUubGl2ZS5jb22CCzNkLmxpdmUuY29tghNhcGkuc2VhcmNoLmxp
dmUuY29tghRiZXRhLnNlYXJjaC5saXZlLmNvbYIVY253ZWIuc2VhcmNoLmxpdmUu
Y29tgg1kaXR1LmxpdmUuY29tghFmYXJlY2FzdC5saXZlLmNvbYIOaW1hZ2UubGl2
ZS5jb22CD2ltYWdlcy5saXZlLmNvbYIRbG9jYWwubGl2ZS5jb20uYXWCFGxvY2Fs
c2VhcmNoLmxpdmUuY29tghRsczRkLnNlYXJjaC5saXZlLmNvbYINbWFpbC5saXZl
LmNvbYIRbWFwaW5kaWEubGl2ZS5jb22CDmxvY2FsLmxpdmUuY29tgg1tYXBzLmxp
dmUuY29tghBtYXBzLmxpdmUuY29tLmF1gg9taW5kaWEubGl2ZS5jb22CDW5ld3Mu
bGl2ZS5jb22CHG9yaWdpbi5jbndlYi5zZWFyY2gubGl2ZS5jb22CFnByZXZpZXcu
bG9jYWwubGl2ZS5jb22CD3NlYXJjaC5saXZlLmNvbYISdGVzdC5tYXBzLmxpdmUu
Y29tgg52aWRlby5saXZlLmNvbYIPdmlkZW9zLmxpdmUuY29tghV2aXJ0dWFsZWFy
dGgubGl2ZS5jb22CDHdhcC5saXZlLmNvbYISd2VibWFzdGVyLmxpdmUuY29tghV3
d3cubG9jYWwubGl2ZS5jb20uYXWCFHd3dy5tYXBzLmxpdmUuY29tLmF1ghN3ZWJt
YXN0ZXJzLmxpdmUuY29tghhlY24uZGV2LnZpcnR1YWxlYXJ0aC5uZXSCDHd3dy5i
aW5nLmNvbTAMBgNVHRMBAf8EAjAAMGoGA1UdHwRjMGEwX6BdoFuGWWh0dHA6Ly93
d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMEF6dXJlJTIw
UlNBJTIwVExTJTIwSXNzdWluZyUyMENBJTIwMDguY3JsMGYGA1UdIARfMF0wUQYM
KwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0
LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTAIBgZngQwBAgIwHwYDVR0j
BBgwFoAU9n4vvYCjSrJwW+vfmh/Y7cphgAcwHQYDVR0lBBYwFAYIKwYBBQUHAwIG
CCsGAQUFBwMBMA0GCSqGSIb3DQEBDAUAA4ICAQCXK5365FWyZxImxacFHAxSE+wO
GMWDQF04YTNlGI8je9UcfenvXdIVrQJfNyo1JMJW/XFGCC8xmCRZLvKJRkDqBD3P
jzpo90t7PRlwVoOh07oHRcHGih8gIBNHptvwn/Oy1kk3iiDcV4gh9EYWcH2LxDtp
tWMBE2hiKtrMAuL34/wdHQMw7K3Tb31HpOOqOpic0yiUOn5tOIAE8tUU+dzEarQV
2w5ezi7TlZRyQ+gnt+Ir+DyC+TBf9CoOuQzpFf4glPDlt5VYLHi+KlgsdZbAQ2b4
B8YR0H+xF5/eTRDgprt4/m9bk65pmjt69e3aORUPPPjEJOqKdlOA4p5Y5E+ELsOq
v3VImLxqZ3Ol2xSHJylag9l3O4IcLm1lr0WWiHWrFaU6o0cBEoVaPEU7YNQ6lQmF
8NkXjVd34Kd8rb9+l4adENPHIzpAfeB48MtLKM2TLy630EkFHPWOFzIoBfn6/QOn
4T+htYy9E6DC+ubXRZa8fck/rlKW35OdzKNSxnf5sB/lnX6uKrL024oT9v/pNJOx
x21OFECacO8dqkw94vx++lzS/utJaQ0agQhh5txtmAaOplEFvR8X1wlTQwPPm3Ji
d37fiwwkG3jPSz7UQslGzt86Uz+VlhlGBwaXT8eS/RSmL8RBYro30utRYmAF4lmL
439ea68yck8AsoFpcA==
-----END CERTIFICATE-----
去掉前后的-----BEGIN CERTIFICATE-----,-----END CERTIFICATE-----并解码base64。
30 82 0d 59 30 82 0b 41,base64 解码后前八个字节,最后两个字节0x0b41 指示剩下的部分的长度。tbs=30 82 0b 41加上tbs的0xb41个字节。对这部分进行对应的hash后就能验证了。
import base64,hashlib
f=open(r'C:\Users\Administrator\Desktop\cert\www.bing.com','rb').read()
content=f.split(b'-')[10]
b64de=base64.b64decode(content.replace(b'\r\n',b''))
len1=int.from_bytes(b64de[6:8],'big')
tbs=b64de[4:8+len1]
sha384=hashlib.sha384(tbs).hexdigest()
print('hash:',sha384)
hash: f0b5b67540085f352c9652c17655ece83bedc6ac86e490bbda003123f08d28ae5087e389f1dcf978e96c282d755bb5b6
target:f0b5b67540085f352c9652c17655ece83bedc6ac86e490bbda003123f08d28ae5087e389f1dcf978e96c282d755bb5b6
总结:
用上一级CA的公钥解密对应私钥加密的签名数据,提取其中的hash值,并对证书的tbs部分进行对应的hash,比较两个hash一致性,这就是验签。
此例使用 RSA 加密的 PKCS #1 SHA-384