解码 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)。