2017-05-22 89 views
0

嘗試驗證PDF簽名不起作用。 PDF由Adobe Acrobat簽名,然後嘗試使用客戶端證書的公鑰進行驗證。C#驗證PDF簽名

因此,我得到客戶端證書的公鑰,散列PDF並驗證哈希是否等於pdf簽名,但失敗。

HttpClientCertificate cert = request.ClientCertificate; 
X509Certificate2 cert2 = new X509Certificate2(cert.Certificate); 

PdfReader pdfreader = new PdfReader("path_to_file"); 

AcroFields fields = pdfreader.AcroFields; 
AcroFields.Item item = fields.GetFieldItem("Signature1"); 
List<string> names = fields.GetSignatureNames(); 

foreach (string name in names){ 
    PdfDictionary dict = fields.GetSignatureDictionary(name); 
    PdfPKCS7 pkcs7 = fields.VerifySignature(name); 
    Org.BouncyCastle.X509.X509Certificate pdfSign = pkcs7.SigningCertificate; 

    // Get its associated CSP and public key 
    RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert2.PublicKey.Key; 

    // Hash the data 
    SHA256 sha256 = new SHA256Managed(); 

    byte[] pdfBytes = System.IO.File.ReadAllBytes("path_to_pdf"); 
    byte[] hash = sha256.ComputeHash(pdfBytes); 

    // Verify the signature with the hash 
    bool ok = csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), pdfSing.GetSignature()); 
} 

回答

1

首先,以驗證是否簽名正確,你可以簡單地使用你已經獲取的PdfPKCS7對象,更確切地說它Verify方法:

/** 
* Verify the digest. 
* @throws SignatureException on error 
* @return <CODE>true</CODE> if the signature checks out, <CODE>false</CODE> otherwise 
*/ 
virtual public bool Verify() 

因此,你可以簡單地調用

bool ok = pkcs7.Verify(); 

oktrue只有在文檔散列符合簽名中的散列。


關於你試圖計算這樣

byte[] pdfBytes = System.IO.File.ReadAllBytes("path_to_pdf"); 
byte[] hash = sha256.ComputeHash(pdfBytes); 

這確實給你完整的PDF的哈希值的文件哈希。

對於帶有集成簽名(如PDF)的文檔類型,這不是感興趣的散列,因爲完整的PDF顯然包含集成簽名!

因此,您必須在PDF中找到爲簽名保留的空間,並在散列計算期間忽略它,參見參考資料。 this answer信息安全堆棧交流,特別是這一形象:

How integrated PDF signatures are "integrated"

在多個簽名的情況下,你還必須考慮到前面的簽名只簽了PDF的前改版,所以散列是要僅爲文件的起始段計算,參見從這個answer referenced above圖像:

enter link description here

的iText的(夏普)方法PdfPKCS7.Verify()考慮到這一切。

+0

優秀的答案!謝謝 – A77ak

+0

@mkl你有什麼想法,我們怎樣才能得到pdf的字節除了簽名值?這樣我們可以重新計算簽名pdf中的哈希值? –

+0

@emrenevayeshirazi你可以簡單地採用iText'AcroFields'類的代碼,看看它的'verifySignature'方法和''updateByteRange''方法。 – mkl