C# 在MemoryStream中创建的iTextSharp符号PDF
我需要动态创建一个PDF文件,所以我使用MemoryStream和iTextSharp来编辑PDF。但我想在将PDF文件发送到浏览器之前对其进行数字签名。我在一个示例项目中看到,iTextSharp有一个PDFSigner类,它主要完成所有工作。但正如我所见,它是这样工作的:C# 在MemoryStream中创建的iTextSharp符号PDF,c#,pdf,itextsharp,digital-signature,C#,Pdf,Itextsharp,Digital Signature,我需要动态创建一个PDF文件,所以我使用MemoryStream和iTextSharp来编辑PDF。但我想在将PDF文件发送到浏览器之前对其进行数字签名。我在一个示例项目中看到,iTextSharp有一个PDFSigner类,它主要完成所有工作。但正如我所见,它是这样工作的: PDFSigner signer = new PDFSigner(inputFileName, outputFileName, certificate, metaData); signer.Sign(......) 但对
PDFSigner signer = new PDFSigner(inputFileName, outputFileName, certificate, metaData);
signer.Sign(......)
但对于MemoryStream,我也不能为输入或输出提供物理文件名。我的代码如下:
MemoryStream memoryStream = new MemoryStream();
var document = new Document(iTextSharp.text.PageSize.LETTER, 40, 40, 60, 40);
PdfWriter.GetInstance(document, memoryStream).CloseStream = false;
document.Open();
PopulatePDF(document, someId);
document.Close();
byte[] byteArray = memoryStream.ToArray();
memoryStream.Write(byteArray, 0, byteArray.Length);
memoryStream.Position = 0;
return new FileStreamResult(memoryStream, "application/pdf");
我的问题是,如果PDFSigner只接受字符串-文件名作为参数,我如何使用PDFSigner对象对文档进行签名。正如Chris Haas所解释的,iText中没有名为
PDFSigner
的类。您可能正在使用非官方版本的iText,在这种情况下,您需要确保正确应用了数字签名
你可以在我写的书中读到更多关于正确数字签名的内容
基本上,这就是使用PKCS#12密钥库进行签名的方式:
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = "My reason for signing";
appearance.Location = "The middle of nowhere";
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(parameters, DigestAlgorithms.SHA256);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
Pkcs12Store-store=新的Pkcs12Store(新文件流(KEYSTORE,FileMode.Open),密码);
字符串别名=”;
i收集链=新列表();
//搜索私钥
foreach(存储中的字符串al.alias)
if(store.IsKeyEntry(al)和&store.GetKey(al.Key.IsPrivate){
别名=al;
打破
}
AsymmetricKeyEntry pk=store.GetKey(别名);
foreach(X509CertificateEntry c in store.GetCertificateChain(别名))
添加(c.证书);
RsaPrivateCrtKeyParameters=pk.Key作为RsaPrivateCrtKeyParameters;
PdfReader读取器=新PdfReader(src);
FileStream os=新FileStream(dest,FileMode.Create);
PdfStamper stamper=PdfStamper.CreateSignature(读卡器,操作系统,'\0');
//创建外观
PDFSignaturePearance外观=母版。SignaturePearance;
外观.Reason=“我签字的原因”;
外观。位置=“无处可去的中央”;
外观:SetVisibleSignature(新矩形(36748144780),1,“sig”);
//创建签名
IExternalSignature pks=新的PrivateKeySignature(参数,DigestAlgorithms.SHA256);
MakeSignature.signDistached(外观、pks、链、null、null、null、0、CryptoStandard.CMS);
显然,您希望用获取撤销信息甚至允许时间戳的实现来替换null
值,但这不是您的问题
你的问题是:我能提供一个只存在于内存中的PDF吗?答案是肯定的:创建
PdfReader
实例时的src
参数可以是指向磁盘上文件的路径,但也可以是从MemoryStream
获取的byte[]
,我可能是错的,但我不认为iText实际上有一个名为PDFSigner
的类,至少我找不到。你是通过在线教程找到这段代码的吗?另外,您使用的是什么版本的iTextSharp?我使用的是iTextSharp 5.5.3,上面的代码来自这个项目:(它使用一个PDFSigner类来工作并进行签名)谢谢。是的,实际上没有正式的PDFSigner类,我发现的项目的作者创建了这个类作为助手,他在其中使用了PdfStamper。第一行的KEYSTORE的输入是什么?@Cerveser它是指向密钥存储的路径,例如.p12
文件,其中包含一个公钥和私钥对。因为私钥是私有的,所以不能共享。@BrunoLowagie应该读取最后第二行new PrivateKeySignature(参数,…
?