PKCS#7 非分離簽名 - 幫助理解消息結構
我對 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 處,您有
version
1,在 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 2 840 113549 1 9 3) 具有單值 OID 的 contentType (1 2 840 113549 1 7 3) envelopedData 冗餘地指定了被簽名內容的類型
- (1 2 840 113549 1 9 37 3) 在分配給前 RSA 公司並由其分配給 PKCS9 的弧中,但未在該弧中分配,因此無效,其值為八位字節字元串,其含義未知
- (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,並且 - 沒有加密數據。如果有加密數據,解密它會相當複雜,但是由於沒有加密數據,所以也沒有解密數據,並且任何數據的缺失都是相同的缺失,無論如果存在什麼數據會存在’不缺席。儘管消息可能已被篡改以刪除數據;如果是這樣,上面的簽名驗證過程將返回失敗。