Подписать PDF с помощью iTextSharp 5.3.3 и USB-токен
Я новичок в iTextSharp (и StackOverFlow). Я пытаюсь подписать PDF в C#, используя внешний USB-токен. Я пытаюсь использовать код follow, который я выкопал из интернета.
Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
//Get Sertifiacte
X509Certificate2 certClient = null;
X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser);
st.Open(OpenFlags.MaxAllowed);
X509Certificate2Collection collection = X509Certificate2UI.SelectFromCollection(st.Certificates, "Please choose certificate:", "", X509SelectionFlag.SingleSelection);
if (collection.Count > 0){
certClient = collection[0];
}
st.Close();
//Get Cert Chain
IList<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>();
X509Chain x509chain = new X509Chain();
x509chain.Build(certClient );
foreach (X509ChainElement x509ChainElement in x509chain.ChainElements){
chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
}
PdfReader reader = new PdfReader(sourceDocument);
FileStream resStream = new FileStream(resultDocument, FileMode.Create, FileAccess.ReadWrite);
PdfStamper stamper = PdfStamper.CreateSignature(reader, resStream , '', null, true);
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(20, 10, 170, 60), 1, "Signed");
X509Certificate2Signature es = new X509Certificate2Signature(certClient, "SHA-1");
MakeSignature.SignDetached(appearance, es, chain, null, null, null, 0, CryptoStandard.CMS);
проблема в том, что я получаю исключение:
System.Security.Cryptography.CryptographicException was unhandled
Message=Invalid type specified.
Source=mscorlib
StackTrace:
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.Utils._GetKeyParameter(SafeKeyHandle hKey, UInt32 paramID)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at iTextSharp.text.pdf.security.X509Certificate2Signature..ctor(X509Certificate2 certificate, String hashAlgorithm)
at WindowsFormsApplication1.PDFSignerHelper.signPdfFile(String sourceDocument, String resultDocument, X509Certificate2 certClient, String reason, String location)
InnerException:
3 ответов
этот подход отлично работает для нас (iTextSharp 5.3.3). Мы используем смарт-карту и USB-токен (поставщик -www.author.kiev.ua):
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);
X509Certificate2 cert = sel[0];
Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
cp.ReadCertificate(cert.RawData)};
IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1");
PdfReader pdfReader = new PdfReader(pathToBasePdf);
signedPdf = new FileStream(pathToBasePdf, FileMode.Create);
pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '');
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
signatureAppearance.SignatureGraphic = Image.GetInstance(pathToSignatureImage);
signatureAppearance.SetVisibleSignature(new Rectangle(100, 100, 250, 150), pdfReader.NumberOfPages, "Signature");
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION;
MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
Я сделал проект C#, который может подписать PDF из магазина windows, смарт-карты или файла Pfx/P12 Может быть, это может быть полезно четыре вы
using System;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace SignPdf
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private SecureString GetSecurePin(string PinCode)
{
SecureString pwd = new SecureString();
foreach (var c in PinCode.ToCharArray()) pwd.AppendChar(c);
return pwd;
}
private void button1_Click(object sender, EventArgs e)
{
//Sign from SmartCard
//note : ProviderName and KeyContainerName can be found with the dos command : CertUtil -ScInfo
string ProviderName = textBox2.Text;
string KeyContainerName = textBox3.Text;
string PinCode = textBox4.Text;
if (PinCode != "")
{
//if pin code is set then no windows form will popup to ask it
SecureString pwd = GetSecurePin(PinCode);
CspParameters csp = new CspParameters(1,
ProviderName,
KeyContainerName,
new System.Security.AccessControl.CryptoKeySecurity(),
pwd);
try
{
RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(csp);
// the pin code will be cached for next access to the smart card
}
catch (Exception ex)
{
MessageBox.Show("Crypto error: " + ex.Message);
return;
}
}
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = null;
if ((ProviderName == "") || (KeyContainerName == ""))
{
MessageBox.Show("You must set Provider Name and Key Container Name");
return;
}
foreach (X509Certificate2 cert2 in store.Certificates)
{
if (cert2.HasPrivateKey)
{
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert2.PrivateKey;
if (rsa == null) continue; // not smart card cert again
if (rsa.CspKeyContainerInfo.HardwareDevice) // sure - smartcard
{
if ((rsa.CspKeyContainerInfo.KeyContainerName == KeyContainerName) && (rsa.CspKeyContainerInfo.ProviderName == ProviderName))
{
//we find it
cert = cert2;
break;
}
}
}
}
if (cert == null)
{
MessageBox.Show("Certificate not found");
return;
}
SignWithThisCert(cert);
}
private void button2_Click(object sender, EventArgs e)
{
//Sign with certificate selection in the windows certificate store
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = null;
//manually chose the certificate in the store
X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);
if (sel.Count > 0)
cert = sel[0];
else
{
MessageBox.Show("Certificate not found");
return;
}
SignWithThisCert(cert);
}
private void button3_Click(object sender, EventArgs e)
{
//Sign from certificate in a pfx or a p12 file
string PfxFileName = textBox5.Text;
string PfxPassword = textBox6.Text;
X509Certificate2 cert = new X509Certificate2(PfxFileName, PfxPassword);
SignWithThisCert(cert);
}
private void SignWithThisCert(X509Certificate2 cert)
{
string SourcePdfFileName = textBox1.Text;
string DestPdfFileName = textBox1.Text + "-Signed.pdf";
Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(cert.RawData) };
IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1");
PdfReader pdfReader = new PdfReader(SourcePdfFileName);
FileStream signedPdf = new FileStream(DestPdfFileName, FileMode.Create); //the output pdf file
PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '');
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
//here set signatureAppearance at your will
signatureAppearance.Reason = "Because I can";
signatureAppearance.Location = "My location";
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
//MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CADES);
MessageBox.Show("Done");
}
}
}
тот же код, что и выше, но использует файл сертификата вместо хранилища для подписи PDF-документа на последней странице.
X509Certificate2 cert = new X509Certificate2("C:\mycert.p12");
Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
cp.ReadCertificate(cert.RawData)};
IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1");
PdfReader pdfReader = new PdfReader("C:\multi-page-pdf.pdf");
var signedPdf = new FileStream("C:\multi-page-pdf-signed.pdf", FileMode.Create);
var pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '');
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
signatureAppearance.SignatureGraphic = Image.GetInstance("C:\logo.png");
signatureAppearance.Reason = "Because I can";
signatureAppearance.Location = "My location";
signatureAppearance.SetVisibleSignature(new Rectangle(100, 100, 250, 150), pdfReader.NumberOfPages, "Signature");
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION;
MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
копировать, вставлять, импортировать необходимые библиотеки и работать над чем-то еще.