2014-05-02 53 views
2

在驗證PDF文件中的簽名時會出現問題。在標準中說:PKCS#7中的消息摘要過程(PDF中的簽名)

消息摘要計算過程的結果取決於signedAttrs字段是否存在。當該字段不存在時,結果就是如上所述的內容的消息摘要。然而,當字段存在時,結果是signedAttrs字段中包含的SignedAttrs值的完整DER編碼的消息摘要。

我解析簽名,並得到signedAttrs

[0](4 elem) 
    SEQUENCE(2 elem) 
     OBJECT IDENTIFIER1.2.840.113549.1.9.3   // ContentType 
     SET(1 elem) 
     OBJECT IDENTIFIER1.2.840.113549.1.7.1 
    SEQUENCE(2 elem) 
     OBJECT IDENTIFIER1.2.840.113549.1.9.5   // SigningTime 
     SET(1 elem) 
     UTCTime2014-04-13 02:58:41 UTC 
    SEQUENCE(2 elem) 
     OBJECT IDENTIFIER1.2.840.113549.1.9.4   // MessageDigest 
     SET(1 elem) 
     OCTET STRING(20 byte) 194E0BA9C4B9A53D5E9E5B7B94D7DB42BEA4C28F 
    SEQUENCE(2 elem) 
     OBJECT IDENTIFIER1.2.840.113549.1.9.15 
     SET(1 elem) 
     SEQUENCE(8 elem) 
      SEQUENCE(1 elem) 
      OBJECT IDENTIFIER2.16.840.1.101.3.4.1.42 
      SEQUENCE(1 elem) 
      OBJECT IDENTIFIER2.16.840.1.101.3.4.1.22 
      SEQUENCE(1 elem) 
      OBJECT IDENTIFIER2.16.840.1.101.3.4.1.2 
      SEQUENCE(1 elem) 
      OBJECT IDENTIFIER1.2.840.113549.3.7 
      SEQUENCE(2 elem) 
      OBJECT IDENTIFIER1.2.840.113549.3.2 
      INTEGER128 
      SEQUENCE(2 elem) 
      OBJECT IDENTIFIER1.2.840.113549.3.2 
      INTEGER64 
      SEQUENCE(1 elem) 
      OBJECT IDENTIFIER1.3.14.3.2.7 
      SEQUENCE(2 elem) 
      OBJECT IDENTIFIER1.2.840.113549.3.2 
      INTEGER40 

和DER編碼:

A081D8301806092A864886F70D010903310B06092A864886F70D010701301C06092A864886F70D010905310F170D3134303431333032353834315A302306092A864886F70D01090431160414194E0BA9C4B9A53D5E9E5B7B94D7DB42BEA4C28F307906092A864886F70D01090F316C306A300B060960864801650304012A300B0609608648016503040116300B0609608648016503040102300A06082A864886F70D0307300E06082A864886F7 0D030202020080300D06082A864886F70D0302020140300706052B0E030207300D06082A864886F70D0302020128

我計算出其消化,並與加密的摘要的解密的結果。但它失敗了。

我應該計算整個signedAttrs字段或某些屬性或其他任何東西的摘要?

編輯: 這是PDF file我想驗證

回答

5

我計算出其消化,並與加密的摘要進行解密的結果。但它失敗了。

我應該計算整個signedAttrs字段或某些屬性或其他任何東西的摘要?

你有沒有考慮

包含在已簽名領域的已簽名值的完整DER編碼的消息摘要

意味着它不是散列值爲的SignedAttrs值本身,但其完整的DER e ncoding?所不同的是,已簽名值是隱含0標記:

signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL 

其完整的DER編碼是沒有的。標準甚至明確這樣說:

一個單獨的編碼已簽名字段的 被用於消息摘要計算執行的。 signed_ttrs中的IMPLICIT [0]標記不用於DER 編碼,而是使用EXPLICIT SET OF標記。也就是說,EXPLICIT SET OF標記的DER 編碼,而不是IMPLICIT [0] 標記,必須包含在消息摘要計算中,以及SignedAttributes值的長度和內容八位字節。

(參見部分都RFC 3852的5.4和RFC 5652

因此,你必須更換領導0XA0在

A081D8301806092A864886F70D010903310B06092A864886F70D010701301C06092A864886F70 ...

因此在計算摘要之前。

你有沒有進一步考慮的加密解密結果消化(我希望你說的是老式的RSA簽名,否則解密是沒有幫助)是肉眼摘要而是消化包裹在DigestInfo結構?

DigestInfo ::= SEQUENCE { 
    digestAlgorithm DigestAlgorithmIdentifier, 
    digest Digest } 

加成

即使這些說明出現了一些問題後,比照註釋

我計算消化的完整DER編碼,但它消化是不同的解密後

因此,這裏有點用充氣城堡Java代碼(也許不是最佳的使用,我更在家裏用禮加密庫)來計算簽署屬性的散列和RSA簽名提取哈希:

// The CMS container 
    CMSSignedData cms = new CMSSignedData(bytes); 

    // Calculating the digest of the signed attributes 
    SignerInformation signerInformation = (SignerInformation) (cms.getSignerInfos().getSigners().iterator().next()); 
    byte[] derSignedAttributes = signerInformation.getEncodedSignedAttributes(); 
    MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); 
    byte[] derSignedAttributesHash = sha1.digest(derSignedAttributes); 

    // Retrieving the public key from the (single) certificate in the container 
    X509CertificateHolder cert = (X509CertificateHolder) cms.getCertificates().getMatches(new Selector() { 
     public boolean match(Object arg0) { return true; } 
     public Object clone()    { return this; } 
    }).iterator().next(); 
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(cert.getSubjectPublicKeyInfo().getEncoded()); 
    KeyFactory keyFactory = KeyFactory.getInstance(publicKeySpec.getFormat()); 
    Key key = keyFactory.generatePublic(publicKeySpec); 

    // Decrypting the DigestInfo from the RSA signature 
    Cipher asymmetricCipher = Cipher.getInstance("RSA", "BC"); 
    asymmetricCipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] digestInfo = asymmetricCipher.doFinal(signerInformation.getSignature()); 
    DigestInfo digestInfoObject = new DigestInfo(ASN1Sequence.getInstance(digestInfo)); 

    System.out.println("Signed Attributes: " + toHex(derSignedAttributes)); 
    System.out.println("Signed Attributes Hash: " + toHex(derSignedAttributesHash)); 
    System.out.println("DigestInfo: " + toHex(digestInfo)); 
    System.out.println("DigestInfo Hash: " + toHex(digestInfoObject.getDigest())); 

在所提供的PDF文件signed_1047_ctsv.pdf輸出應用到簽名是:

Signed Attributes: 31 81 D8 30 18 06 09 2A 86 48 86 F7 0D 01 09 03 31 0B 06 09 2A 86 48 86 F7 0D 01 07 01 30 1C 06 09 2A 86 48 86 F7 0D 01 09 05 31 0F 17 0D 31 34 30 34 31 33 30 32 35 38 34 31 5A 30 23 06 09 2A 86 48 86 F7 0D 01 09 04 31 16 04 14 19 4E 0B A9 C4 B9 A5 3D 5E 9E 5B 7B 94 D7 DB 42 BE A4 C2 8F 30 79 06 09 2A 86 48 86 F7 0D 01 09 0F 31 6C 30 6A 30 0B 06 09 60 86 48 01 65 03 04 01 2A 30 0B 06 09 60 86 48 01 65 03 04 01 16 30 0B 06 09 60 86 48 01 65 03 04 01 02 30 0A 06 08 2A 86 48 86 F7 0D 03 07 30 0E 06 08 2A 86 48 86 F7 0D 03 02 02 02 00 80 30 0D 06 08 2A 86 48 86 F7 0D 03 02 02 01 40 30 07 06 05 2B 0E 03 02 07 30 0D 06 08 2A 86 48 86 F7 0D 03 02 02 01 28 
Signed Attributes Hash: 7A 2D D8 92 B0 F4 AC 5A 2C 93 03 6B 06 94 74 62 71 D0 06 17 
DigestInfo: 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 7A 2D D8 92 B0 F4 AC 5A 2C 93 03 6B 06 94 74 62 71 D0 06 17 
DigestInfo Hash: 7A 2D D8 92 B0 F4 AC 5A 2C 93 03 6B 06 94 74 62 71 D0 06 17 

正如你看到的,值簽名屬性散列DigestInfo哈希是相同的。

+0

感謝您的回答。我不明白什麼是完整的DER編碼?你可以給我一個例子嗎? – xuanhai266

+1

簽名屬性包含在帶有IMPLICIT [0]標籤(編碼爲0xA0)的PKCS#7容器中。這意味着這個標籤*代替了'SET OF'標籤(編碼爲0x31),它將'SignedAttributes'定義爲它的外部初始標籤。對於*完整的DER編碼*,您必須將其恢復,即將0xA0再次替換爲0x31。 – mkl

+0

因此,在這種情況下,完整的DER編碼爲: '3181d8301806092a864886f70d010903310b06092a864886f70d010701301c06092a864886f70d010905310f170d3134303431333032353834315a302306092a864886f70d01090431160414194e0ba9c4b9a53d5e9e5b7b94d7db42bea4c28f307906092a864886f70d01090f316c306a300b060960864801650304012a300b0609608648016503040116300b0609608648016503040102300a06082a864886f70d0307300e06082a864886f70d030202020080300d06082a864886f70d0302020140300706052b0e030207300d06082a864886f70d0302020128' 我會計算消化它? – xuanhai266