2017-09-15 939 views
1

我已經過所有類似的問題,但找不到應用itextsharp延遲簽名的情況。數字簽名(PKCS#7-延期簽名)/自從應用簽名以後文檔已被更改或損壞

基本上,我的應用程序使用由遠程Web服務創建的PKCS#7簽名來簽署pdf文檔。

我的應用程序發送這個Web服務的原始文件的散列(在添加空簽名字段後的可簽名字節的散列),並且接收Base64編碼的簽名文件。

我將此簽名嵌入到之前生成的具有空簽名字段的臨時pdf文件中。

最後,我的簽名未經驗證,因爲Adobe Reader表示文檔已更改或已損壞。這增加空白簽名域和獲取全文

public static string GetBytesToSign(string unsignedPdf, string tempPdf, string signatureFieldName) 
{ 
    if (File.Exists(tempPdf)) 
     File.Delete(tempPdf); 

    using (PdfReader reader = new PdfReader(unsignedPdf)) 
    { 
     using (FileStream os = File.OpenWrite(tempPdf)) 
     { 
      PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0'); 
      PdfSignatureAppearance appearance = stamper.SignatureAppearance; 
      appearance.SetVisibleSignature(new Rectangle(36, 748, 250, 400), 1, signatureFieldName); 

      IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED); 

      MakeSignature.SignExternalContainer(appearance, external, 8192); 

      byte[] array = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream()); 

      return Convert.ToBase64String(array); 
     } 
    } 
} 

的可簽名字節作爲該操作tempPdf的結果

碼被生成並予接收的散列PDF文檔的可簽名的字節從該tempPdf文件。

然後使用下面的代碼,我重新打開此tempFile並嵌入Base64編碼的PKCS#7簽名。打開臨時的PDF和將接收到的簽名

public static void EmbedSignature(string tempPdf, string signedPdf, string signatureFieldName, string signature) 
{ 
    byte[] signedBytes = Convert.FromBase64String(signature); 

    using (PdfReader reader = new PdfReader(tempPdf)) 
    { 
     using (FileStream os = File.OpenWrite(signedPdf)) 
     { 
      IExternalSignatureContainer external = new MyExternalSignatureContainer(signedBytes); 
      MakeSignature.SignDeferred(reader, signatureFieldName, os, external); 
     } 
    } 
} 

由於這種操作我最後signedPdf的結果

代碼生成。但是,Adobe表示簽名由於更改或損壞而無效。

enter image description here

My Original File

Temporary File Generated For Signing

Final Signed File

我發送到Web服務的臨時文件文件的哈希值是:

z9qIyvtp4cRBZ1SSCQ + P0JVRinz5lv jYjXk3L7YP/IE =

我從web服務接收的簽名是:

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 

我比較TEMPFILE和signedFile的字節,僅臨時文件的零(其用於臨時簽名文件我想)被signedFile中的實際簽名替換。

enter image description here

enter image description here

我真的停留在這一點上。我不知道我應該在哪裏看下。

+0

你確定'GetBytesToSign'中的'return'行確實返回'Convert.FromBase64String(array)'而不是'Convert.ToBase64String(array)'?前者沒有任何意義,'array'不是base64字符串,因此它不可能是從base64字符串轉換*的參數。 – mkl

+0

對不起這是一個錯字,修復它。我正在做GetBytesToSign之外的轉換,並在寫入問題的同時將其轉移到方法中。 –

+0

Raadol Hallederiz ..... – sotn

回答

1

在您從Web服務接收到的署名有:

39 59: . . . SEQUENCE { 
    41 9: . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) 
     : . . . . . (PKCS #7) 
    52 46: . . . . [0] { 
    54 44: . . . . . OCTET STRING  
     : . . . . . . 7A 39 71 49 79 76 74 70 z9qIyvtp 
     : . . . . . . 34 63 52 42 5A 31 53 53 4cRBZ1SS 
     : . . . . . . 43 51 2B 50 30 4A 56 52 CQ+P0JVR 
     : . . . . . . 69 6E 7A 35 6C 76 6A 59 inz5lvjY 
     : . . . . . . 6A 58 6B 33 4C 37 59 50 jXk3L7YP 
     : . . . . . . 2F 49 45 3D    /IE= 
     : . . . . . } 
     : . . . . } 
[...] 
1955 9: . . . . . SEQUENCE { 
1957 5: . . . . . . OBJECT IDENTIFIER sha1 (1 3 14 3 2 26) 
     : . . . . . . . (OIW) 
1964 0: . . . . . . NULL 
     : . . . . . . } 
1966 93: . . . . . [0] { 
1968 24: . . . . . . SEQUENCE { 
1970 9: . . . . . . . OBJECT IDENTIFIER contentType (1 2 840 113549 1 9 3) 
     : . . . . . . . . (PKCS #9) 
1981 11: . . . . . . . SET { 
1983 9: . . . . . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1) 
     : . . . . . . . . . (PKCS #7) 
     : . . . . . . . . } 
     : . . . . . . . } 
1994 28: . . . . . . SEQUENCE { 
1996 9: . . . . . . . OBJECT IDENTIFIER signingTime (1 2 840 113549 1 9 5) 
     : . . . . . . . . (PKCS #9) 
2007 15: . . . . . . . SET { 
2009 13: . . . . . . . . UTCTime 22/09/2017 13:18:38 GMT 
     : . . . . . . . . } 
     : . . . . . . . } 
2024 35: . . . . . . SEQUENCE { 
2026 9: . . . . . . . OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4) 
     : . . . . . . . . (PKCS #9) 
2037 22: . . . . . . . SET { 
2039 20: . . . . . . . . OCTET STRING  
     : . . . . . . . . . EF 37 38 3B B1 31 AB 96 .78;.1.. 
     : . . . . . . . . . CE FC 47 1E 32 A7 79 73 ..G.2.ys 
     : . . . . . . . . . 5D 95 15 04    ]... 
     : . . . . . . . . } 
     : . . . . . . . } 
     : . . . . . . } 
2061 13: . . . . . SEQUENCE { 
2063 9: . . . . . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) 
     : . . . . . . . (PKCS #1) 
2074 0: . . . . . . NULL 
     : . . . . . . } 

在這裏您base64編碼的散列顯示爲嵌入式簽名數據(偏移56..99)。此外,哈希算法被選爲「SHA-1」(偏移1955..1965),簽名文檔哈希是一個20字節的值,它與SHA-1哈希值的大小相匹配。此外,RSA用於PKCS#11.5(偏移量2061..2075)中所述的簽名。

因此,它看起來像您的簽名服務不使用您的輸入作爲base64編碼預先計算的文檔哈希值,但作爲明文數據使用SHA1withRSA/2048進行簽名。

所以錯誤不在您的iText中使用代碼,而是在您的簽名服務調用代碼中。

+0

非常感謝。儘管我明確要求籤名使用base64編碼的散列值,但該服務正在返回我共享的簽名。 –

+0

所以簽名是無效的,因爲用於簽名的SHA1算法? –

+0

不可以。因爲您提供服務的數據已經是文檔數據的哈希值,但是該服務將它們作爲原始數據進行處理,但仍然應該進行哈希處理。 – mkl