C# 验证 PDF 签名
C# Verifying PDF signature
尝试验证 PDF 签名无效。 PDF 由 Adobe Acrobat 签名,然后尝试使用客户端证书的 public 密钥对其进行验证。
所以我得到了客户端证书的public密钥,对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());
}
首先,要验证签名是否正确,您可以简单地使用您已经检索到的 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();
并且 ok
仅当文档哈希与签名中的哈希匹配时才为 true
。
关于您尝试像这样计算文档哈希
byte[] pdfBytes = System.IO.File.ReadAllBytes("path_to_pdf");
byte[] hash = sha256.ComputeHash(pdfBytes);
这确实为您提供了完整 PDF.
的哈希值
不过,对于像 PDF 这样具有集成签名的文档类型,这不是我们感兴趣的散列,因为完整的 PDF 显然包含集成签名!
因此,您必须找到PDF中为签名保留的space,并在哈希计算时忽略它,参见。 this answer 在 Information Security Stack Exchange 上,特别是这张图片:
如果有多个签名,您还必须考虑到较早的签名仅签署 PDF 的先前修订版,因此仅针对文件的起始段计算哈希值,请参见。此图片来自 answer referenced above:
iText(Sharp) 方法PdfPKCS7.Verify()
考虑了所有这些。
尝试验证 PDF 签名无效。 PDF 由 Adobe Acrobat 签名,然后尝试使用客户端证书的 public 密钥对其进行验证。
所以我得到了客户端证书的public密钥,对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());
}
首先,要验证签名是否正确,您可以简单地使用您已经检索到的 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();
并且 ok
仅当文档哈希与签名中的哈希匹配时才为 true
。
关于您尝试像这样计算文档哈希
byte[] pdfBytes = System.IO.File.ReadAllBytes("path_to_pdf");
byte[] hash = sha256.ComputeHash(pdfBytes);
这确实为您提供了完整 PDF.
的哈希值不过,对于像 PDF 这样具有集成签名的文档类型,这不是我们感兴趣的散列,因为完整的 PDF 显然包含集成签名!
因此,您必须找到PDF中为签名保留的space,并在哈希计算时忽略它,参见。 this answer 在 Information Security Stack Exchange 上,特别是这张图片:
如果有多个签名,您还必须考虑到较早的签名仅签署 PDF 的先前修订版,因此仅针对文件的起始段计算哈希值,请参见。此图片来自 answer referenced above:
iText(Sharp) 方法PdfPKCS7.Verify()
考虑了所有这些。