我正在用c#开发一个web服务器,它执行数字签名验证,以确保pdf文件没有被修改。我使用的是iText和iTextSharp。
但是客户端是基于java applet。我在java applet中执行数字签名。在java中,我可以制作签名,然后验证它们。但是如果我在c#中验证签名,它会给出一个nullreferenceexception。
这是我的Java数字签名代码:
String path = "C:/Users/a/Desktop/cert.pfx";
String keystore_password = "fgf";
String key_password = "fgf";
////
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
ks.load(new FileInputStream(path), keystore_password.toCharArray());
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
PdfReader reader = new PdfReader(src);
dest = "C:/Users/a/Desktop/" + dest;
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, ' ');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
和c#验证码:
PdfReader reader = new PdfReader(pdfFile);
AcroFields af = reader.AcroFields;
var names = af.GetSignatureNames();
if (names.Count == 0)
{
throw new InvalidOperationException("No Signature present in pdf file.");
}
foreach (string name in names)
{
if (!af.SignatureCoversWholeDocument(name))
{
throw new InvalidOperationException(string.Format("The signature: {0} does not covers the whole document.", name));
}
PdfPKCS7 pk = af.VerifySignature(name);
var cal = pk.SignDate;
var pkc = pk.Certificates;
if (!pk.Verify())
{
Console.WriteLine("The signature is not valid.");
return false;
}
}
在af.VerifySignature(name);抛出NullReferenceException !
有趣的是,如果我用c#代码执行签名,我可以在java中验证它,因为我添加了这些指令:BouncyCastleProvider provider = new BouncyCastleProvider(); Security.addProvider(供应商);我认为我的问题依赖于一些字节转换…但是在c#中,我不知道如何调用bouncycastleprovider。
你能帮我吗?我最诚挚的问候:William。
OP在注释中发布的堆栈跟踪
...
at org.bouncycastle.security.SignerUtil.getSigner(String algorithm)
at iTextSharp.text.pdf.PdfPKCS7..ctor(Byte[] contentsKey)
at iTextSharp.text.pdf.AcroFields.VerifySignature(String name)
at SignatureLibrary.iText.PDFValidation(String pdfFile)
in ...\SignatureLibrary\SignatureLibrary\iText.cs:line 122
包含iTextSharp.text.pdf.PdfPKCS7..ctor(Byte[] contentsKey)
行,这表明OP使用的不是当前的iTextSharp 5.5.0版本,而是5.3.0之前的版本(发布于2012年6月):在5.3.0版本中,PdfPKCS7
被重构到命名空间iTextSharp.text.pdf.security
中。
这次重构是整个ittext签名创建和验证代码主要更新的一部分,这次更新引入了许多新特性。
因此,OP被建议更新iTextSharp程序集,并且确实:
我下载了最新的itextsharp版本,经过验证它运行良好。