我正在玩 RSA 来学习和理解。
我从浏览器获得了以下 PEM 文件(BASE 64)
-----BEGIN CERTIFICATE-----
MIIE/jCCA+agAwIBAgISBGzkPWVoI1CDdChcRxp7jO1hMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yNDAyMTAwMzQ2MjFaFw0yNDA1MTAwMzQ2MjBaMBkxFzAVBgNVBAMT
Dmh0dHBzLWd1aWRlLmRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
p7jmFSTUYpTTIN/Qvvh9/cXNTvPY5+3sCLfxn+2DMQs+wi+tGX31n5Wk3G0GRg9q
XQ9awYaeIEjYWDpLHzwlWB5PNk1FhzO3ZYPgBDrQAqBI1TSPhQNmIm8WA5V5juQl
yEGI9efqZOuFm+1oIqFFbNtQ4ty/Vg6+FuJJx6KaRUmhQ6hpypuW4cz81ytVVJ0i
6E4rDE+jcQEHoRPxQ9K8/WkjCCuzUEdklGy9t+Jv4fUjlI2AKvhVOJKzBO8UjhTV
+tjCBR/PTmWq5Xi5NXmKx34/sgHNqx86DQ9xDiAv3X8jOiHK5eH5PhV1xKmp9BGq
OaQwG8JSDHsdt2qgy2xlnQIDAQABo4ICJTCCAiEwDgYDVR0PAQH/BAQDAgWgMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1Ud
DgQWBBRD3wUGbTVubIcA7UYVRBcRVP9XcDAfBgNVHSMEGDAWgBQULrMXt1hWy65Q
CUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUHMAGGFWh0dHA6Ly9y
My5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3IzLmkubGVuY3Iub3Jn
LzAtBgNVHREEJjAkgg5odHRwcy1ndWlkZS5kZYISd3d3Lmh0dHBzLWd1aWRlLmRl
MBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDxAHcA
SLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMAAAGNkVaAmwAABAMASDBG
AiEA+YNF9WpuxNwggP9a0qHI1TXZK6ykYazxSMZDgJAqV34CIQDl05SPwsN+uDBg
PKBbu3RtPCuzXVRvSDMvggQd/lUoyAB2AKLiv9Ye3i8vB6DWTm03p9xlQ7DGtS6i
2reK+Jpt9RfYAAABjZFWgQkAAAQDAEcwRQIhANkJGz5gIcPrQEMerOTz+Y/X7KLG
JIaHP5jKiJd+OIxYAiAB+KbOm64IxyM+T8Kyr4SRimc05QEiHEaUw1zuUud8dTAN
BgkqhkiG9w0BAQsFAAOCAQEAAhTC1jNPx0WEW65qYjotHJPUsGN/PxwdQnloPcPn
gI5sq/H1jCwxaaw2DpOdD8fwAfYKMdtgQG2oKTeIRjn/AvpdYUab7S1WkC61LpGw
6lEZH2dp8Krcy0xL8BcCUR+ET2x+Zb3UKjkafZNW9XCQuRi8f6tlpJ5BpEhcJCQ6
2eU5Y10BnBZk+KiSV1rocAUtVM3Gy1m0MB6tBXayCXhOoHBmOjw/z591+k8ahOzA
DNxW3uX9Tfak/15XRKRp+Je5YpKV/8ww+LX4tO4vCK72RaD4QSsb2LRORH6BoLZA
lDPil4lBDrB40ojuGV8KaMmq88Sf2bCSTYX1pt/5bOtOyw==
-----END CERTIFICATE-----
Subject Name
CN (Common Name): https-guide.de
Issuer Name
C (Country): US
O (Organization): Let's Encrypt
CN (Common Name): R3
Issued Certificate
Version: 3
Serial Number: 04 6C E4 3D 65 68 23 50 83 74 28 5C 47 1A 7B 8C ED 61
Not Valid Before: 2024-02-10
Not Valid After: 2024-05-10
Certificate Fingerprints
SHA1: 0D 0D 1A 18 7D 9A 59 8E 40 5C 71 3B CF 46 14 E3 6B 5E B5 05
MD5: 9A AC AA 7E 7D 51 22 0E F0 DB 89 C8 67 A4 67 DF
Public Key Info
Key Algorithm: RSA
Key Parameters: 05 00
Key Size: 2048
Key SHA1 Fingerprint: 29 A8 72 98 2E 6E 88 D0 F8 AB 0C C7 65 D4 56 95 94 2E F9 2E
Public Key: 30 82 01 0A 02 82 01 01 00 A7 B8 E6 15 24 D4 62 94 D3 20 DF D0 BE F8 7D FD C5 CD 4E F3 D8 E7 ED EC 08 B7 F1 9F ED 83 31 0B 3E C2 2F AD 19 7D F5 9F 95 A4 DC 6D 06 46 0F 6A 5D 0F 5A C1 86 9E 20 48 D8 58 3A 4B 1F 3C 25 58 1E 4F 36 4D 45 87 33 B7 65 83 E0 04 3A D0 02 A0 48 D5 34 8F 85 03 66 22 6F 16 03 95 79 8E E4 25 C8 41 88 F5 E7 EA 64 EB 85 9B ED 68 22 A1 45 6C DB 50 E2 DC BF 56 0E BE 16 E2 49 C7 A2 9A 45 49 A1 43 A8 69 CA 9B 96 E1 CC FC D7 2B 55 54 9D 22 E8 4E 2B 0C 4F A3 71 01 07 A1 13 F1 43 D2 BC FD 69 23 08 2B B3 50 47 64 94 6C BD B7 E2 6F E1 F5 23 94 8D 80 2A F8 55 38 92 B3 04 EF 14 8E 14 D5 FA D8 C2 05 1F CF 4E 65 AA E5 78 B9 35 79 8A C7 7E 3F B2 01 CD AB 1F 3A 0D 0F 71 0E 20 2F DD 7F 23 3A 21 CA E5 E1 F9 3E 15 75 C4 A9 A9 F4 11 AA 39 A4 30 1B C2 52 0C 7B 1D B7 6A A0 CB 6C 65 9D 02 03 01 00 01
Key Usage
Usages: Digital signature
Key encipherment
Critical: Yes
Extended Key Usage
Allowed Purposes: Server Authentication
Client Authentication
Critical: No
Basic Constraints
Certificate Authority: No
Max Path Length: Unlimited
Critical: Yes
Subject Key Identifier
Key Identifier: 43 DF 05 06 6D 35 6E 6C 87 00 ED 46 15 44 17 11 54 FF 57 70
Critical: No
Extension
Identifier: 2.5.29.35
Value: 30 16 80 14 14 2E B3 17 B7 58 56 CB AE 50 09 40 E6 1F AF 9D 8B 14 C2 C6
Critical: No
Extension
Identifier: 1.3.6.1.5.5.7.1.1
Value: 30 47 30 21 06 08 2B 06 01 05 05 07 30 01 86 15 68 74 74 70 3A 2F 2F 72 33 2E 6F 2E 6C 65 6E 63 72 2E 6F 72 67 30 22 06 08 2B 06 01 05 05 07 30 02 86 16 68 74 74 70 3A 2F 2F 72 33 2E 69 2E 6C 65 6E 63 72 2E 6F 72 67 2F
Critical: No
Subject Alternative Names
DNS: https-guide.de
DNS: www.https-guide.de
Critical: No
Extension
Identifier: 2.5.29.32
Value: 30 0A 30 08 06 06 67 81 0C 01 02 01
Critical: No
Extension
Identifier: 1.3.6.1.4.1.11129.2.4.2
Value: 04 81 F3 00 F1 00 77 00 48 B0 E3 6B DA A6 47 34 0F E5 6A 02 FA 9D 30 EB 1C 52 01 CB 56 DD 2C 81 D9 BB BF AB 39 D8 84 73 00 00 01 8D 91 56 80 9B 00 00 04 03 00 48 30 46 02 21 00 F9 83 45 F5 6A 6E C4 DC 20 80 FF 5A D2 A1 C8 D5 35 D9 2B AC A4 61 AC F1 48 C6 43 80 90 2A 57 7E 02 21 00 E5 D3 94 8F C2 C3 7E B8 30 60 3C A0 5B BB 74 6D 3C 2B B3 5D 54 6F 48 33 2F 82 04 1D FE 55 28 C8 00 76 00 A2 E2 BF D6 1E DE 2F 2F 07 A0 D6 4E 6D 37 A7 DC 65 43 B0 C6 B5 2E A2 DA B7 8A F8 9A 6D F5 17 D8 00 00 01 8D 91 56 81 09 00 00 04 03 00 47 30 45 02 21 00 D9 09 1B 3E 60 21 C3 EB 40 43 1E AC E4 F3 F9 8F D7 EC A2 C6 24 86 87 3F 98 CA 88 97 7E 38 8C 58 02 20 01 F8 A6 CE 9B AE 08 C7 23 3E 4F C2 B2 AF 84 91 8A 67 34 E5 01 22 1C 46 94 C3 5C EE 52 E7 7C 75
Critical: No
Signature
Signature Algorithm: 1.2.840.113549.1.1.11
Signature Parameters: 05 00
Signature: 02 14 C2 D6 33 4F C7 45 84 5B AE 6A 62 3A 2D 1C 93 D4 B0 63 7F 3F 1C 1D 42 79 68 3D C3 E7 80 8E 6C AB F1 F5 8C 2C 31 69 AC 36 0E 93 9D 0F C7 F0 01 F6 0A 31 DB 60 40 6D A8 29 37 88 46 39 FF 02 FA 5D 61 46 9B ED 2D 56 90 2E B5 2E 91 B0 EA 51 19 1F 67 69 F0 AA DC CB 4C 4B F0 17 02 51 1F 84 4F 6C 7E 65 BD D4 2A 39 1A 7D 93 56 F5 70 90 B9 18 BC 7F AB 65 A4 9E 41 A4 48 5C 24 24 3A D9 E5 39 63 5D 01 9C 16 64 F8 A8 92 57 5A E8 70 05 2D 54 CD C6 CB 59 B4 30 1E AD 05 76 B2 09 78 4E A0 70 66 3A 3C 3F CF 9F 75 FA 4F 1A 84 EC C0 0C DC 56 DE E5 FD 4D F6 A4 FF 5E 57 44 A4 69 F8 97 B9 62 92 95 FF CC 30 F8 B5 F8 B4 EE 2F 08 AE F6 45 A0 F8 41 2B 1B D8 B4 4E 44 7E 81 A0 B6 40 94 33 E2 97 89 41 0E B0 78 D2 88 EE 19 5F 0A 68 C9 AA F3 C4 9F D9 B0 92 4D 85 F5 A6 DF F9 6C EB 4E CB
1)如何手动验证签名?
我知道发行者是“Let's Encrypt”
我从 PEM 文件链中获取了 Let's Encrypt 的公钥
#PUBLIC KEY
exponent: 65537
modulo: BB:02:15:28:CC:F6:A0:94:D3:0F:12:EC:8D:55:92:C3:F8:82:F1:99:A6:7A:42:88:A7:5D:26:AA:B5:2B:B9:C5:4C:B1:AF:8E:6B:F9:75:C8:A3:D7:0F:47:94:14:55:35:57:8C:9E:A8:A2:39:19:F5:82:3C:42:A9:4E:6E:F5:3B:C3:2E:DB:8D:C0:B0:5C:F3:59:38:E7:ED:CF:69:F0:5A:0B:1B:BE:C0:94:24:25:87:FA:37:71:B3:13:E7:1C:AC:E1:9B:EF:DB:E4:3B:45:52:45:96:A9:C1:53:CE:34:C8:52:EE:B5:AE:ED:8F:DE:60:70:E2:A5:54:AB:B6:6D:0E:97:A5:40:34:6B:2B:D3:BC:66:EB:66:34:7C:FA:6B:8B:8F:57:29:99:F8:30:17:5D:BA:72:6F:FB:81:C5:AD:D2:86:58:3D:17:C7:E7:09:BB:F1:2B:F7:86:DC:C1:DA:71:5D:D4:46:E3:CC:AD:25:C1:88:BC:60:67:75:66:B3:F1:18:F7:A2:5C:E6:53:FF:3A:88:B6:47:A5:FF:13:18:EA:98:09:77:3F:9D:53:F9:CF:01:E5:F5:A6:70:17:14:AF:63:A4:FF:99:B3:93:9D:DC:53:A7:06:FE:48:85:1D:A1:69:AE:25:75:BB:13:CC:52:03:F5:ED:51:A1:8B:DB:15
我尝试使用简短的浏览器控制台 Javascript 手动验证签名
var modulo="BB:02:15:28:CC:F6:A0:94:D3:0F:12:EC:8D:55:92:C3:F8:82:F1:99:A6:7A:42:88:A7:5D:26:AA:B5:2B:B9:C5:4C:B1:AF:8E:6B:F9:75:C8:A3:D7:0F:47:94:14:55:35:57:8C:9E:A8:A2:39:19:F5:82:3C:42:A9:4E:6E:F5:3B:C3:2E:DB:8D:C0:B0:5C:F3:59:38:E7:ED:CF:69:F0:5A:0B:1B:BE:C0:94:24:25:87:FA:37:71:B3:13:E7:1C:AC:E1:9B:EF:DB:E4:3B:45:52:45:96:A9:C1:53:CE:34:C8:52:EE:B5:AE:ED:8F:DE:60:70:E2:A5:54:AB:B6:6D:0E:97:A5:40:34:6B:2B:D3:BC:66:EB:66:34:7C:FA:6B:8B:8F:57:29:99:F8:30:17:5D:BA:72:6F:FB:81:C5:AD:D2:86:58:3D:17:C7:E7:09:BB:F1:2B:F7:86:DC:C1:DA:71:5D:D4:46:E3:CC:AD:25:C1:88:BC:60:67:75:66:B3:F1:18:F7:A2:5C:E6:53:FF:3A:88:B6:47:A5:FF:13:18:EA:98:09:77:3F:9D:53:F9:CF:01:E5:F5:A6:70:17:14:AF:63:A4:FF:99:B3:93:9D:DC:53:A7:06:FE:48:85:1D:A1:69:AE:25:75:BB:13:CC:52:03:F5:ED:51:A1:8B:DB:15",
signature="02 14 C2 D6 33 4F C7 45 84 5B AE 6A 62 3A 2D 1C 93 D4 B0 63 7F 3F 1C 1D 42 79 68 3D C3 E7 80 8E 6C AB F1 F5 8C 2C 31 69 AC 36 0E 93 9D 0F C7 F0 01 F6 0A 31 DB 60 40 6D A8 29 37 88 46 39 FF 02 FA 5D 61 46 9B ED 2D 56 90 2E B5 2E 91 B0 EA 51 19 1F 67 69 F0 AA DC CB 4C 4B F0 17 02 51 1F 84 4F 6C 7E 65 BD D4 2A 39 1A 7D 93 56 F5 70 90 B9 18 BC 7F AB 65 A4 9E 41 A4 48 5C 24 24 3A D9 E5 39 63 5D 01 9C 16 64 F8 A8 92 57 5A E8 70 05 2D 54 CD C6 CB 59 B4 30 1E AD 05 76 B2 09 78 4E A0 70 66 3A 3C 3F CF 9F 75 FA 4F 1A 84 EC C0 0C DC 56 DE E5 FD 4D F6 A4 FF 5E 57 44 A4 69 F8 97 B9 62 92 95 FF CC 30 F8 B5 F8 B4 EE 2F 08 AE F6 45 A0 F8 41 2B 1B D8 B4 4E 44 7E 81 A0 B6 40 94 33 E2 97 89 41 0E B0 78 D2 88 EE 19 5F 0A 68 C9 AA F3 C4 9F D9 B0 92 4D 85 F5 A6 DF F9 6C EB 4E CB",
signature_decrypt;
modulo=BigInt("0x"+modulo.replace(new RegExp(":","g"),""));
signature=BigInt("0x"+signature.replace(new RegExp(" ","g"),""));
signature_decrypt=signature;
for (let i=0;i<16;i++) //-- exponent: 65537 -> 2**16=65536
{
signature_decrypt=signature_decrypt**2n % modulo
}
signature_decrypt=signature_decrypt*signature % modulo //65537
console.log (signature_decrypt.toString(16));
我得到以下输出:
1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420bc56117d619d50579b700bd9e3fd275a2009234dbf413c89e13c0d12664188ff
由于我得到的填充,我认为这是正确的解密签名,但我不知道应该从 pem 文件的哪一部分构建 sha256 哈希值,因为我没有相等 - 或者我的解密是错误的
完整的 pem 文件包括签名,所以我认为应该在之前的部分上制作sha256值,但具体在哪里。有人可以帮忙吗?
第二个问题:pem SHA256 内部有两个证书时间戳
48:B0:E3:6B:DA:A6:47:34:0F:E5:6A:02:FA:9D:30:EB:1C:52:01:CB:56:DD:2C:81:D9:BB:BF:AB:39:D8:84:73
A2:E2:BF:D6:1E:DE:2F:2F:07:A0:D6:4E:6D:37:A7:DC:65:43:B0:C6:B5:2E:A2:DA:B7:8A:F8:9A:6D:F5:17:D8
谁制作的,它们是关于什么的,为什么是两个? - 有人可以链接一个页面,其中一个 pem 文件逐行解释,因为我搜索了它并且只得到了一般的 bla, bla, bla
答案1
- 我尝试手动验证签名....由于我得到的填充,我认为这是正确的解密签名,但我不知道应该从 pem 文件的哪一部分构建 sha256 哈希值,因为我没有平等 - 或者我的解密是错误的。完整的pem文件包含签名,所以我认为应该在之前的部分上制作sha256值,但具体在哪里。
你说的基本上是对的,但需要精确。
首先,PEM 格式只是一个包装器——它将一些二进制数据表示为围绕 Base64 编码的破折号 BEGIN 和破折号结束线,并使用字母表 A-Za-z0-9+/ padding = 和换行符。看一个很好的简短描述或者现行标准。
对于 PEM 格式证书,二进制数据是ASN.1 DER 编码的3 个元素的序列:
“待签名”(TBS)部分,也称为证书正文或“信息”,本身是一个相当复杂的子序列;
一个标识签名算法的“AlgorithmIdentifier”(并且在主体内冗余重复),一个以对象标识符开头的序列;和
包含签名值的位串。
因此,通过对 PEM 主体进行 Base64 解码而获得的证书数据包含外部 SEQUENCE 的标头;编码的TBS;编码的算法标识符;和编码的位串。所有这些都是可变长度的,因此通常您必须查看编码以找出每个编码的开始和结束位置。签名是在第 1 项(TBS)上计算的,对于您的示例证书,它从字节偏移 4 开始,长度为 1002 字节。
来自另一个方向,RSA-PKCS1-v1_5 签名恢复(通过 modexp e)“代表”其中包括
一字节 01,给定密钥大小 = 模数大小的情况下尽可能多的字节 FF,以及一字节 00
DigestInfo SEQUENCE 的 DER 编码,包含 AlgorithmIdentifier(类似于外层的 AlgorithmIdentifier,但这里仅针对哈希而不是完整签名)加上包含实际哈希字节的 OCTET STRING。
您恢复的值减去 01 FF...00 填充是
3031300d060960864801650304020105000420bc56117d619d50579b700bd9e3fd275a2009234dbf413c89e13c0d12664188ff
解码为
3031 # tag-length for the outer SEQUENCE
300d # tag-length for the AlgId SEQUENCE
0609608648016503040201 # OBJECT IDENTIFIER for SHA256
0500 # NULL for parameters
0420 # tag-length for the OCTET STRING
bc56117d619d50579b700bd9e3fd275a2009234dbf413c89e13c0d12664188ff # actual bytes of hash
果然,如果我从您的数据中取出从 4 开始的字节(即 1002)并计算 SHA256,我就会得到该哈希值。
请注意,DigestInfo 结构非常简单,它也可以表示为仅取决于添加到哈希值和从哈希值中删除的哈希算法的前缀,如我给出的 RFC8017 链接的下一页所示。
第二个问题:pem SHA256 48:B0:E3:6B:DA:A6:47:34:0F:E5:6A:02:FA:9D:30:EB:1C:52:01内有两个证书时间戳:CB:56:DD:2C:81:D9:BB:BF:AB:39:D8:84:73
A2:E2:BF:D6:1E:DE:2F:2F:07:A0:D6:4E: 6D:37:A7:DC:65:43:B0:C6:B5:2E:A2:DA:B7:8A:F8:9A:6D:F5:17:D8
这些并不是时间戳。使用以下命令查看信息更丰富的解码openssl x509 -text
:
CT Precertificate SCTs:
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : 48:B0:E3:6B:DA:A6:47:34:0F:E5:6A:02:FA:9D:30:EB:
1C:52:01:CB:56:DD:2C:81:D9:BB:BF:AB:39:D8:84:73
Timestamp : Feb 10 04:46:21.851 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:46:02:21:00:F9:83:45:F5:6A:6E:C4:DC:20:80:FF:
5A:D2:A1:C8:D5:35:D9:2B:AC:A4:61:AC:F1:48:C6:43:
80:90:2A:57:7E:02:21:00:E5:D3:94:8F:C2:C3:7E:B8:
30:60:3C:A0:5B:BB:74:6D:3C:2B:B3:5D:54:6F:48:33:
2F:82:04:1D:FE:55:28:C8
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : A2:E2:BF:D6:1E:DE:2F:2F:07:A0:D6:4E:6D:37:A7:DC:
65:43:B0:C6:B5:2E:A2:DA:B7:8A:F8:9A:6D:F5:17:D8
Timestamp : Feb 10 04:46:21.961 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:21:00:D9:09:1B:3E:60:21:C3:EB:40:43:1E:
AC:E4:F3:F9:8F:D7:EC:A2:C6:24:86:87:3F:98:CA:88:
97:7E:38:8C:58:02:20:01:F8:A6:CE:9B:AE:08:C7:23:
3E:4F:C2:B2:AF:84:91:8A:67:34:E5:01:22:1C:46:94:
C3:5C:EE:52:E7:7C:75
它们是两个 SCT 的 Logid。 SCT是签名证书时间戳,是一个结构体含有时间戳和签名,由日志操作员生成,该日志操作员将证书信息(通常在本例中为所谓的“预证书”)提交给公共可信日志,目的是:证书透明度。
PS:你也可以看看https://security.stackexchange.com/questions/127095/manually-walking-through-the-signature-validation-of-a-certificate其中详细介绍了使用 openssl 的类似过程。