我需要使用Windows证书存储区中存在的证书来签署PDF文档。我一整天都在努力想弄明白,而且我如此接近但到目前为止。
所有缺失的是:如何获取IExternalSignature对象以对PDF文件进行签名?
Rahul Singla写了一个很好的例子,说明了如何使用新的iText 5.3.0 API签署PDF文档 - 只要你就可以访问你的.pfx文件了PC在某处。
使用来自Windows证书存储区的证书进行签名时有a previous question,但它使用的是SetCrypto
仍然存在的API版本,签名显然是可选的。在iText 5.3.0中,API已发生变化,SetCrypto
不再是一个问题。
这是我到目前为止的内容(为后代添加的评论,因为这可能是如何在'网络上执行此操作的最完整和最新版本):
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using BcX509 = Org.BouncyCastle.X509;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Crypto;
using DotNetUtils = Org.BouncyCastle.Security.DotNetUtilities;
...
// Set up the PDF IO
PdfReader reader = new PdfReader(@"some\dir\SomeTemplate.pdf");
PdfStamper stamper = PdfStamper.CreateSignature(reader,
new FileStream(@"some\dir\SignedPdf.pdf", FileMode.Create), '\0');
PdfSignatureAppearance sap = stamper.SignatureAppearance;
sap.Reason = "For no apparent raisin";
sap.Location = "...";
// Acquire certificate chain
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
X509CertificateCollection certCollection =
certStore.Certificates.Find(X509FindType.FindBySubjectName,
"My.Cert.Subject", true);
X509Certificate cert = certCollection[0];
// iTextSharp needs this cert as a BouncyCastle X509 object; this converts it.
BcX509.X509Certificate bcCert = DotNetUtils.FromX509Certificate(cert);
var chain = new List<BcX509.X509Certificate> { bcCert };
certStore.Close();
// Ok, that's the certificate chain done. Now how do I get the PKS?
IExternalSignature signature = null; /* ??? */
// Sign the PDF file and finish up.
MakeSignature.SignDetached(sap, signature, chain, // the important stuff
null, null, null, 0, CryptoStandard.CMS);
stamper.Close();
正如你所看到的那样:除了签名之外我什么都没有,而且我很难知道如何获得它!
答案 0 :(得分:3)
X509Certificate cert = certCollection[0]; // Your code
X509Certificate2 signatureCert = new X509Certificate2(cert);
var pk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(signatureCert.PrivateKey).Private;
如果你有pk,可以如上所述,你创建一个IExternalSignature,如下所示:
IExternalSignature es = new PrivateKeySignature(pk, "SHA-256");
您还可以找到以下使用条款:
答案 1 :(得分:0)
请在PDF and digital signatures上下载该书。您将在第3章中找到有关如何使用Windows证书库进行签名的Java示例。如您所见,您需要Windows-MY密钥库。
现在转到我们发布C# port of these examples的存储库。寻找C3_11_SignWithToken.cs。
X509Store x509Store = new X509Store("My");
x509Store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = x509Store.Certificates;
IList<X509Certificate> chain = new List<X509Certificate>();
X509Certificate2 pk = null;
if (certificates.Count > 0) {
X509Certificate2Enumerator certificatesEn = certificates.GetEnumerator();
certificatesEn.MoveNext();
pk = certificatesEn.Current;
X509Chain x509chain = new X509Chain();
x509chain.Build(pk);
foreach (X509ChainElement x509ChainElement in x509chain.ChainElements) {
chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
}
}
x509Store.Close();
如果我理解正确,chain
和pk
是您要查找的变量;
答案 2 :(得分:0)
public byte[] SignPdf(byte[] pdf)
{
using (MemoryStream output = new MemoryStream())
{
//get certificate from path
X509Certificate2 cert1 = new X509Certificate2(@"C:\temp\certtemp.pfx", "12345", X509KeyStorageFlags.Exportable);
//get private key to sign pdf
var pk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(cert1.PrivateKey).Private;
// convert the type to be used at .SetCrypt();
Org.BouncyCastle.X509.X509Certificate bcCert = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(cert1);
// get the pdf u want to sign
PdfReader pdfReader = new PdfReader(pdf);
PdfStamper stamper = PdfStamper.CreateSignature(pdfReader, output, '\0');
PdfSignatureAppearance pdfSignatureAppearance = stamper.SignatureAppearance;
//.SetCrypt(); sign the pdf
pdfSignatureAppearance.SetCrypto(pk, new Org.BouncyCastle.X509.X509Certificate[] { bcCert }, null, PdfSignatureAppearance.WINCER_SIGNED);
pdfSignatureAppearance.Reason = "Este documento está assinado digitalmente pelo Estado Portugues";
pdfSignatureAppearance.Location = " Lisboa, Portugal";
pdfSignatureAppearance.SignDate = DateTime.Now;
stamper.Close();
return output.ToArray();
}
}
我使用此代码获取byte[]
PDF并再次返回已签名的byte[]
PDF。
这是iTextSharp-LGPL。