2013-02-21 126 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。

相關問題