解码 ASN.1 - PKCS#7 非分离签名
Decode ASN.1 - PKCS#7 non-detached signature
我对 ASN.1 格式还很陌生。我有一个 PKCS#7 签名,在执行 ASNdump 后看起来像下面的签名。有人可以帮我理解下面每个元素的含义吗?我只能在签名中识别出 2 个证书,但无法确认哪一个用于什么用途。如果您能阐明我应该如何解码、验证此签名和解密数据,也非常感谢。
0 904: SEQUENCE {
4 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
15 889: [0] {
19 885: SEQUENCE {
23 1: INTEGER 1
26 11: SET {
28 9: SEQUENCE {
30 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
37 0: NULL
: }
: }
39 404: SEQUENCE {
43 9: OBJECT IDENTIFIER envelopedData (1 2 840 113549 1 7 3)
54 389: [0] {
58 385: SEQUENCE {
62 1: INTEGER 0
65 348: SET {
69 344: SEQUENCE {
73 1: INTEGER 0
76 63: SEQUENCE {
78 43: SEQUENCE {
80 11: SET {
82 9: SEQUENCE {
84 3: OBJECT IDENTIFIER countryName (2 5 4 6)
89 2: PrintableString 'US'
: }
: }
93 12: SET {
95 10: SEQUENCE {
97 3: OBJECT IDENTIFIER organizationName (2 5 4 10)
102 3: PrintableString 'ABC'
: }
: }
107 14: SET {
109 12: SEQUENCE {
111 3: OBJECT IDENTIFIER commonName (2 5 4 3)
116 5: PrintableString 'CA'
: }
: }
: }
123 16: INTEGER 0A 01 41 7E 00 74 01 51 8F 8F 74 7E 8F 4D A6 B5
: }
141 13: SEQUENCE {
143 9: OBJECT IDENTIFIER rsaOAEP (1 2 840 113549 1 1 7)
154 0: SEQUENCE {}
: }
156 257: BIT STRING
: C2 A1 7A FA B2 08 1C CC CA BB 46 96 FA 1D 84 6C
Truncated
: }
: }
417 28: SEQUENCE {
419 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
430 15: SEQUENCE {
432 7: OBJECT IDENTIFIER '1 2 840 10047 1 1'
441 4: SEQUENCE {
443 2: BIT STRING 6 unused bits
: '10'B (bit 1)
: }
: }
: }
: }
: }
: }
447 457: SET {
451 453: SEQUENCE {
455 1: INTEGER 1
458 63: SEQUENCE {
460 43: SEQUENCE {
462 11: SET {
464 9: SEQUENCE {
466 3: OBJECT IDENTIFIER countryName (2 5 4 6)
471 2: PrintableString 'US'
: }
: }
475 12: SET {
477 10: SEQUENCE {
479 3: OBJECT IDENTIFIER organizationName (2 5 4 10)
484 3: PrintableString 'ABC'
: }
: }
489 14: SET {
491 12: SEQUENCE {
493 3: OBJECT IDENTIFIER commonName (2 5 4 3)
498 5: PrintableString 'CA'
: }
: }
: }
505 16: INTEGER 40 01 58 68 58 0E CD A1 CE 86 CD E8 C9 12 46 90
: }
523 9: SEQUENCE {
525 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
532 0: NULL
: }
534 97: [0] {
536 24: SEQUENCE {
538 9: OBJECT IDENTIFIER contentType (1 2 840 113549 1 9 3)
549 11: SET {
551 9: OBJECT IDENTIFIER envelopedData (1 2 840 113549 1 7 3)
: }
: }
562 32: SEQUENCE {
564 10: OBJECT IDENTIFIER '1 2 840 113549 1 9 37 3'
576 18: SET {
578 16: OCTET STRING 85 D5 DA CC C2 97 B5 78 F7 60 52 9F 24 9B 45 74
: }
: }
596 35: SEQUENCE {
598 9: OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
609 22: SET {
611 20: OCTET STRING
: DD 89 06 A7 B4 56 A8 EC F1 DB 9F 69 BA 30 F6 5D
: CB 25 91 98
: }
: }
: }
633 13: SEQUENCE {
635 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
646 0: NULL
: }
648 256: OCTET STRING
: 76 A2 36 CA 5B 8E 01 72 01 42 A7 1B 51 82 55 BD
: truncated ...
: }
: }
: }
: }
: }
这是一个 SignedCms 消息(字节偏移量 4)包装了一个 EnvelopedCms 消息。
(字节偏移量 43)。
消息由序列号为 40 01 58 68 58 0E CD A1 CE 86 CD E8 C9 12 46 90
(字节偏移量 505)和颁发者“CN=CA,O=ABC,C=US”(字节偏移量 460)的证书签名。它使用 RSA-SHA1 (PKCS#1 v1.5 padding) 签名。
签名的有效载荷(EnvelopedCms)让我感到困惑,因为字节偏移量 443 显示了一个 BIT STRING,而我不希望它出现(因此看不到应该位于该位置的数据)。我能说的是,它是用一个目标收件人加密的,该收件人是证书的持有者,证书的序列号为 0A 01 41 7E 00 74 01 51 8F 8F 74 7E 8F 4D A6 B5
(字节偏移量 123),来自颁发者“CN=CA,O=ABC,C=US” (字节偏移量 78)。
--编辑:至于请求的字段:
- 字节偏移量 648:这是来自签名者的 RSA-PKCS1-SHA1 签名。
- 字节偏移量 156:这是 ktri.encryptedKey 应该在的位置。但那应该是 OCTET STRING,而不是 BIT STRING。这是 AES/3DES/whatever 密钥的 RSA 加密版本。
- 字节偏移量 578:这应该是编码的 PKCS#9 非结构化名称。但是从这个解析输出来看它似乎不合法。
额外编辑:字节偏移量 443 应该是一个以 OID (0x06) 开头的序列 (0x30),但它是一个具有 6 位未使用位字段的位字符串 (0x03)。好像有人在某处向后设置了一个十六进制常量。
至于如何阅读...如果您使用 .NET 并使用 C#:
SignedCms signedCms = new SignedCms();
signedCms.Decode(message);
// Throws on failure
signedCms.CheckSignature(true);
SignerInfoCollection signers = signedCms.SignerInfos;
if (signers.Count != 1 || signers[0].Certificate == null)
{
throw new InvalidOperationException("I don't know how to verify the signer trust");
}
// Exercise left to the reader
if (!IsSignerTrustedForThisMessage(signers[0].Certificate))
{
throw new CryptographicException();
}
EnvelopedCms envelopedCms = new EnvelopedCms();
envelopedCms.Decode(signedCms.ContentInfo.Content);
// If you know the expected certificate(s) for decryption
envelopedCms.Decrypt(candidateCertsWithPrivateKey);
// (which will search certificate stores if it can't find a match)
// otherwise `envelopedCms.Decrypt();` will -only- search the cert stores
// It's only the decrypted content after the call to Decrypt, of course.
byte[] decryptedMessage = envelopedCms.ContentInfo.Content;
对于 Win32 C,您需要 CryptMsg* API,而其他平台可能有办法做到这一点,而无需您自己实施 CMS RFC (IETF RFC 5652)。
我对 ASN.1 格式还很陌生。我有一个 PKCS#7 签名,在执行 ASNdump 后看起来像下面的签名。有人可以帮我理解下面每个元素的含义吗?我只能在签名中识别出 2 个证书,但无法确认哪一个用于什么用途。如果您能阐明我应该如何解码、验证此签名和解密数据,也非常感谢。
0 904: SEQUENCE {
4 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
15 889: [0] {
19 885: SEQUENCE {
23 1: INTEGER 1
26 11: SET {
28 9: SEQUENCE {
30 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
37 0: NULL
: }
: }
39 404: SEQUENCE {
43 9: OBJECT IDENTIFIER envelopedData (1 2 840 113549 1 7 3)
54 389: [0] {
58 385: SEQUENCE {
62 1: INTEGER 0
65 348: SET {
69 344: SEQUENCE {
73 1: INTEGER 0
76 63: SEQUENCE {
78 43: SEQUENCE {
80 11: SET {
82 9: SEQUENCE {
84 3: OBJECT IDENTIFIER countryName (2 5 4 6)
89 2: PrintableString 'US'
: }
: }
93 12: SET {
95 10: SEQUENCE {
97 3: OBJECT IDENTIFIER organizationName (2 5 4 10)
102 3: PrintableString 'ABC'
: }
: }
107 14: SET {
109 12: SEQUENCE {
111 3: OBJECT IDENTIFIER commonName (2 5 4 3)
116 5: PrintableString 'CA'
: }
: }
: }
123 16: INTEGER 0A 01 41 7E 00 74 01 51 8F 8F 74 7E 8F 4D A6 B5
: }
141 13: SEQUENCE {
143 9: OBJECT IDENTIFIER rsaOAEP (1 2 840 113549 1 1 7)
154 0: SEQUENCE {}
: }
156 257: BIT STRING
: C2 A1 7A FA B2 08 1C CC CA BB 46 96 FA 1D 84 6C
Truncated
: }
: }
417 28: SEQUENCE {
419 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
430 15: SEQUENCE {
432 7: OBJECT IDENTIFIER '1 2 840 10047 1 1'
441 4: SEQUENCE {
443 2: BIT STRING 6 unused bits
: '10'B (bit 1)
: }
: }
: }
: }
: }
: }
447 457: SET {
451 453: SEQUENCE {
455 1: INTEGER 1
458 63: SEQUENCE {
460 43: SEQUENCE {
462 11: SET {
464 9: SEQUENCE {
466 3: OBJECT IDENTIFIER countryName (2 5 4 6)
471 2: PrintableString 'US'
: }
: }
475 12: SET {
477 10: SEQUENCE {
479 3: OBJECT IDENTIFIER organizationName (2 5 4 10)
484 3: PrintableString 'ABC'
: }
: }
489 14: SET {
491 12: SEQUENCE {
493 3: OBJECT IDENTIFIER commonName (2 5 4 3)
498 5: PrintableString 'CA'
: }
: }
: }
505 16: INTEGER 40 01 58 68 58 0E CD A1 CE 86 CD E8 C9 12 46 90
: }
523 9: SEQUENCE {
525 5: OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
532 0: NULL
: }
534 97: [0] {
536 24: SEQUENCE {
538 9: OBJECT IDENTIFIER contentType (1 2 840 113549 1 9 3)
549 11: SET {
551 9: OBJECT IDENTIFIER envelopedData (1 2 840 113549 1 7 3)
: }
: }
562 32: SEQUENCE {
564 10: OBJECT IDENTIFIER '1 2 840 113549 1 9 37 3'
576 18: SET {
578 16: OCTET STRING 85 D5 DA CC C2 97 B5 78 F7 60 52 9F 24 9B 45 74
: }
: }
596 35: SEQUENCE {
598 9: OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
609 22: SET {
611 20: OCTET STRING
: DD 89 06 A7 B4 56 A8 EC F1 DB 9F 69 BA 30 F6 5D
: CB 25 91 98
: }
: }
: }
633 13: SEQUENCE {
635 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
646 0: NULL
: }
648 256: OCTET STRING
: 76 A2 36 CA 5B 8E 01 72 01 42 A7 1B 51 82 55 BD
: truncated ...
: }
: }
: }
: }
: }
这是一个 SignedCms 消息(字节偏移量 4)包装了一个 EnvelopedCms 消息。 (字节偏移量 43)。
消息由序列号为 40 01 58 68 58 0E CD A1 CE 86 CD E8 C9 12 46 90
(字节偏移量 505)和颁发者“CN=CA,O=ABC,C=US”(字节偏移量 460)的证书签名。它使用 RSA-SHA1 (PKCS#1 v1.5 padding) 签名。
签名的有效载荷(EnvelopedCms)让我感到困惑,因为字节偏移量 443 显示了一个 BIT STRING,而我不希望它出现(因此看不到应该位于该位置的数据)。我能说的是,它是用一个目标收件人加密的,该收件人是证书的持有者,证书的序列号为 0A 01 41 7E 00 74 01 51 8F 8F 74 7E 8F 4D A6 B5
(字节偏移量 123),来自颁发者“CN=CA,O=ABC,C=US” (字节偏移量 78)。
--编辑:至于请求的字段:
- 字节偏移量 648:这是来自签名者的 RSA-PKCS1-SHA1 签名。
- 字节偏移量 156:这是 ktri.encryptedKey 应该在的位置。但那应该是 OCTET STRING,而不是 BIT STRING。这是 AES/3DES/whatever 密钥的 RSA 加密版本。
- 字节偏移量 578:这应该是编码的 PKCS#9 非结构化名称。但是从这个解析输出来看它似乎不合法。
额外编辑:字节偏移量 443 应该是一个以 OID (0x06) 开头的序列 (0x30),但它是一个具有 6 位未使用位字段的位字符串 (0x03)。好像有人在某处向后设置了一个十六进制常量。
至于如何阅读...如果您使用 .NET 并使用 C#:
SignedCms signedCms = new SignedCms();
signedCms.Decode(message);
// Throws on failure
signedCms.CheckSignature(true);
SignerInfoCollection signers = signedCms.SignerInfos;
if (signers.Count != 1 || signers[0].Certificate == null)
{
throw new InvalidOperationException("I don't know how to verify the signer trust");
}
// Exercise left to the reader
if (!IsSignerTrustedForThisMessage(signers[0].Certificate))
{
throw new CryptographicException();
}
EnvelopedCms envelopedCms = new EnvelopedCms();
envelopedCms.Decode(signedCms.ContentInfo.Content);
// If you know the expected certificate(s) for decryption
envelopedCms.Decrypt(candidateCertsWithPrivateKey);
// (which will search certificate stores if it can't find a match)
// otherwise `envelopedCms.Decrypt();` will -only- search the cert stores
// It's only the decrypted content after the call to Decrypt, of course.
byte[] decryptedMessage = envelopedCms.ContentInfo.Content;
对于 Win32 C,您需要 CryptMsg* API,而其他平台可能有办法做到这一点,而无需您自己实施 CMS RFC (IETF RFC 5652)。