2013-02-21 129 views
6

我需要使用Windows证书存储中存在的证书签署PDF文档。我一直在挖掘一整天,试图找出它,而我如此接近如此遥远如何使用Windows Cert Store中的证书签署PDF文档?

所有缺少的是这样的:如何获得IExternalSignature对象以PDF文件签名?

Rahul Singla写的如何注册使用新的iText 5.3.0 API PDF文档一个美丽的例子 - 只要您可以访问.pfx文件在PC上坐着的地方。

使用来自Windows Cert Store的证书进行签名时有a previous question,只是它使用的是API版本,其中SetCrypto仍存在,并且签名显然是可选的。在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

非常有用。谢谢! – 2014-05-19 11:10:24

回答

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"); 

您也可以找到使用下面的文章:

+0

这可以工作(并且您需要首先将该签名'转换为'X509Certificate2'对象)。还有一些证书权限问题需要注意 - 稍后我会添加一些相关信息。 – doppelgreener 2013-02-22 00:14:02

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(); 

如果我理解正确chainpk是你要找的变量;

+0

这教会了我应该如何获得证书链,所以谢谢。然而,那不是我所追求的对象 - 在这种情况下'pk'只是一个X509Certificate2对象。 – doppelgreener 2013-02-22 02:31:01

+1

很好的代码示例,但有点令人困惑。 'pk'可能被解释为私钥,它不是......'pk'是签名证书。 – 2015-10-12 11:37:13

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。

相关问题