Padding

PKCS#7 非分離簽名 - 幫助理解消息結構

  • June 15, 2018

我對 ASN.1 格式很陌生。我有一個 PKCS#7 簽名,它在執行 ASNdump 後看起來像下面的那個。有人可以幫我理解下面每個元素的含義嗎?我只能在簽名中辨識 2 個證書,但無法確認哪個證書用於什麼用途。如果您能闡明我應該如何解碼、驗證此簽名和解密數據,也將不勝感激。


0 904:序列{
4 9:對象標識符簽名數據(1 2 840 113549 1 7 2)
15 889: [0] {
19 885:序列{
23 1:整數 1
26 11:設置{
28 9:序列{
30 5:對象標識符 sha1 (1 3 14 3 2 26)
37 0:空
: }
: }
39 404:序列{
43 9:對象標識符封裝數據(1 2 840 113549 1 7 3)
54 389: [0] {
58 385:序列{
62 1:整數 0
65348:設置{
69 344:序列{
73 1:整數 0
76 63:序列{
78 43:序列{
80 11:設置{
82 9:序列{
84 3:對象標識符國家名稱(2 5 4 6)
89 2:可列印字元串“美國”
: }
: }
93 12:設置{
95 10:序列{
97 3:對象標識符組織名稱(2 5 4 10)
102 3:可列印字元串'ABC'
: }
: }
107 14:設置{
109 12:序列{
111 3:對象標識符 commonName (2 5 4 3)
116 5:可列印字元串“CA”
: }
: }
: }
123 16:整數 0A 01 41 7E 00 74 01 51 8F 8F 74 7E 8F 4D A6 B5
: }
141 13:序列{
143 9:對象標識符 rsaOAEP (1 2 840 113549 1 1 7)
154 0:序列{}
: }
156 257:位串
: C2 A1 7A FA B2 08 1C CC CA BB 46 96 FA 1D 84 6C
截斷
: }
: }
417 28:序列{
419 9:對象標識符數據(1 2 840 113549 1 7 1)
430 15:序列{
432 7:對象標識符“1 2 840 10047 1 1”
441 4:序列{
443 2:位串 6 個未使用的位
: '10'B (位 1)
: }
: }
: }
: }
: }
: }
447 457:設置{
451 453:序列{
455 1:整數 1
458 63:序列{
460 43:序列{
462 11:設置{
464 9:序列{
466 3:對象標識符國家名稱(2 5 4 6)
471 2:可列印字元串“美國”
: }
: }
475 12:設置{
477 10:序列{
479 3:對象標識符組織名稱(2 5 4 10)
484 3:可列印字元串“ABC”
: }
: }
489 14:設置{
491 12:序列{
493 3:對象標識符 commonName (2 5 4 3)
498 5:可列印字元串“CA”
: }
: }
: }
505 16:整數 40 01 58 68 58 0E CD A1 CE 86 CD E8 C9 12 46 90
: }
523 9:序列{
525 5:對象標識符 sha1 (1 3 14 3 2 26)
532 0:空
: }
534 97: [0] {
536 24:序列{
538 9:對象標識符內容類型(1 2 840 113549 1 9 3)
549 11:設置{
551 9:對象標識符封裝數據(1 2 840 113549 1 7 3)
: }
: }
562 32:序列{
564 10:對象標識符“1 2 840 113549 1 9 37 3”
576 18:設置{
578 16:八位字節串 85 D5 DA CC C2 97 B5 78 F7 60 52 9F 24 9B 45 74
: }
: }
596 35:序列{
598 9:對象標識符消息摘要(1 2 840 113549 1 9 4)
609 22:設置{
611 20:八位字元串
: DD 89 06 A7 B4 56 A8 EC F1 DB 9F 69 BA 30 F6 5D
: CB 25 91 98
: }
: }
: }
633 13:序列{
635 9:對象標識符rsa加密(1 2 840 113549 1 1 1)
646 0:空
: }
648 256:八位字元串
: 76 A2 36 CA 5B 8E 01 72 01 42 A7 1B 51 82 55 BD
: 截斷...
: }
: }
: }
: }
: }

對此的實際答案是:使用庫。有很多可用的,它們已經處理了下面的複雜細節,以及更多存在於 PKCS7/CMS 中但在這個相當簡單的情況下不存在的細節。但是,這對於加密來說是題外話;如果您在使用它時遇到特定問題,請嘗試使用 softwarerecs 來幫助選擇一個,並使用 stackoverflow。


CMS 的目前版本(PKCS7 的後續版本)是rfc5652,我將使用它作為最方便的參考,儘管您的消息中使用的功能從很早開始就沒有改變。

任何 PKCS7/CMS 消息的最外層結構在第 3 節中定義:

 ContentInfo ::= SEQUENCE {
   contentType ContentType,
   content [0] EXPLICIT ANY DEFINED BY contentType }

 ContentType ::= OBJECT IDENTIFIER

您有 OID 1 2 840 113549 1 7 2 因此內容是簽名消息,表示為SignedData第 5.1 節等中的類型:

 SignedData ::= SEQUENCE {
   version CMSVersion,
   digestAlgorithms DigestAlgorithmIdentifiers,
   encapContentInfo EncapsulatedContentInfo,
   certificates [0] IMPLICIT CertificateSet OPTIONAL,
   crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
   signerInfos SignerInfos }

 DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier

 SignerInfos ::= SET OF SignerInfo

在偏移量 23 處,您有version1,在 26 處digestAlgorithms由 sha1 的 AlgId(無參數)組成,這是唯一用於簽署此消息的摘要,在 39 處,簽署的內容是嵌套的 PKCS7/CMS 結構,即封裝(加密)消息;我現在將其視為一個 blob,稍後再討論。您沒有 CERTIFICATE(S) 或 CRL(S) 並且在 447 包含一個SignerInfo在 5.3 中定義的 SET,在 X.501 和 X.509 通過 10.2.4 的一些幫助下:

 SignerInfo ::= SEQUENCE {
   version CMSVersion,
   sid SignerIdentifier,
   digestAlgorithm DigestAlgorithmIdentifier,
   signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
   signatureAlgorithm SignatureAlgorithmIdentifier,
   signature SignatureValue,
   unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }

 SignerIdentifier ::= CHOICE {
   issuerAndSerialNumber IssuerAndSerialNumber,
   subjectKeyIdentifier [0] SubjectKeyIdentifier }

 SignedAttributes ::= SET SIZE (1..MAX) OF Attribute

 UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute

 Attribute ::= SEQUENCE {
   attrType OBJECT IDENTIFIER,
   attrValues SET OF AttributeValue }

 AttributeValue ::= ANY

 SignatureValue ::= OCTET STRING

 IssuerAndSerialNumber ::= SEQUENCE {
   issuer Name,
   serialNumber CertificateSerialNumber }

 CertificateSerialNumber ::= INTEGER

在 455 你有版本 1;在 460 的專有名稱 C=US,O=ABC,CN=CA,它是您的簽名者證書的頒發者,並且可能是內部或測試 CA;在 505 處是您的簽名者證書的序列號。如果 CA 根據標準正常執行,則它頒發的每個證書都由頒發者名稱和序列號的組合唯一標識。

在 523 處,您有一個 sha1 的 AlgId,它是簽名的摘要,在 534 處,signedAttrs具有以下元素的隱式標記上下文 0 SET,每個元素都是 OID 加上包含一些值的 SET:

  1. (1 2 840 113549 1 9 3) 具有單值 OID 的 contentType (1 2 840 113549 1 7 3) envelopedData 冗餘地指定了被簽名內容的類型
  2. (1 2 840 113549 1 9 37 3) 在分配給前 RSA 公司並由其分配給 PKCS9 的弧中,但未在該弧中分配,因此無效,其值為八位字節字元串,其含義未知
  3. (1 2 840 113549 1 9 4) messageDigest 的值為一個 OCTET STRING,其中包含簽名內容編碼的 SHA-1 摘要,根據第 5.4 節中所述的規則

最後,在 633 處,您有一個用於簽名算法的 AlgId(在早期版本中稱為摘要加密算法),使用舊 OID 指定 RSA,這意味著該方案最初在 PKCS1v1 中定義,現在在 PKCS1v2+ 中命名為 RSASSA-PKCS1-v1_5 (目前為 rfc8017),在 646 處,包含實際簽名值的 OCTET STRING,對於 RSA,它是一個簡單的字節字元串,表示計算為的無符號整數 $ s = r^e\mod n $ “代表”在哪裡 $ r $ 源自根據第 5.4 節編碼的signedAttrs 的摘要。

因此,要驗證此簽名消息,您需要:

  • 查找或獲取由頒發者名稱和序列號標識的證書
  • 驗證證書以檢查它是由您信任的 CA 頒發的,未被篡改或偽造(證書的簽名使用 CA 的公鑰進行驗證),未過期或被撤銷或以其他方式無效,並允許使用密鑰來簽署數據和如果適用,更具體地允許簽署此消息中的任何類型或類別的數據,並發布給您認為可以合法產生或以其他方式簽署此類數據的個人、組織、系統或其他實體
  • 使用證書中的公鑰和 messageDigest 屬性中的摘要值與重新計算的 encapContentInfo 值摘要驗證 signedAttrs 編碼上的簽名

現在轉向作為簽名內容的封裝數據,它在 6.1 et seq 中定義:

 EnvelopedData ::= SEQUENCE {
   version CMSVersion,
   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
   recipientInfos RecipientInfos,
   encryptedContentInfo EncryptedContentInfo,
   unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }

 OriginatorInfo ::= SEQUENCE {
   certs [0] IMPLICIT CertificateSet OPTIONAL,
   crls [1] IMPLICIT RevocationInfoChoices OPTIONAL }

 RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo

 EncryptedContentInfo ::= SEQUENCE {
   contentType ContentType,
   contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
   encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }

 EncryptedContent ::= OCTET STRING

 UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute

在 62 處,您有版本 0,沒有originatorInfo,在 65 處,RecipientInfo在 6.2 中定義了一個,對於這種情況是 6.2.1:

 KeyTransRecipientInfo ::= SEQUENCE {
   version CMSVersion,  -- always set to 0 or 2
   rid RecipientIdentifier,
   keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
   encryptedKey EncryptedKey }

 RecipientIdentifier ::= CHOICE {
   issuerAndSerialNumber IssuerAndSerialNumber,
   subjectKeyIdentifier [0] SubjectKeyIdentifier }

 EncryptedKey ::= OCTET STRING

在 73 處,您有版本 0,在 73 處是頒發者名稱(與簽名相同),在 123 處有序列號(不同),它們共同標識其公鑰用於加密“內容”密鑰(又名 DEK)的證書,在 141 是密鑰加密算法的 AlgId,它是根據 PKCS1v2 的 RSA-OAEP,在 156 是包裝加密密鑰值的 BIT STRING。

最後,在 417 處,您encryptedContentInfo在 419 處包含數據的 OID,在 430 處包含使用 OID (1 2 840 10047 1 1) 辨識數據加密算法的 AlgId,根據http://oid-info.com由 ANSI X9F 分配到 TDEA ECB,並且 - 沒有加密數據。

如果有加密數據,解密它會相當複雜,但是由於沒有加密數據,所以也沒有解密數據,並且任何數據的缺失都是相同的缺失,無論如果存在什麼數據會存在’不缺席。儘管消息可能已被篡改以刪除數據;如果是這樣,上面的簽名驗證過程將返回失敗。

正如 Cordy 對 Furies 所說的那樣,“知道了,而且,嗯”

引用自:https://crypto.stackexchange.com/questions/60030