问题描述
我正在测试iText 7.1.2.0库,以在C#项目中使用数字证书或智能卡(X509Certificate2)签名pdf文件.但是,当我尝试创建IExternalSignature时遇到此错误.
I am testing the iText 7.1.2.0 library to sign pdf files, using a digital certificate or smart card (X509Certificate2) in a C # project. But I'm getting this error when I try to create the IExternalSignature.
根据该文件中找到(这里,和在此处),实现此过程的方法是使用BouncyCastle库,该库允许从数字证书中提取主密钥,但是,这给了我一个错误,而且我找不到另一种方法.在文档中(此处)它们是从.pfx文件创建的,但是在这种情况下,我需要直接从读卡器中的证书中获取主密钥.在以前的iText版本中,允许使用以下命令进行创建:
According to the documentation found (here, here and here), the way to achieve this process is using the BouncyCastle library that allows extracting the primary keys from the digital certificate, however, it is giving me an error and I can not find another way to do it.In the documentation (here) they are created from .pfx files, but for this case, I need to take the primary keys directly from the certificate in the card reader. In previous versions of iText, it's allowed the creation with the following command:
IExternalSignature externalSignature = new X509Certificate2Signature(Certificate, "SHA-1");
但是在版本7中,它不再可用,并且在文档中,我看不到该怎么做.
But in version 7 it is no longer available and in the documentation I do not see how to do it.
有人使用过iText 7,并且能够使用X509Certificate2进行签名,该X509Certificate2知道创建IExternalSignature的正确方法吗?
Someone has used iText 7 and has been able to sign using an X509Certificate2 that knows the correct way to create the IExternalSignature?
这是我正在使用的代码:
This is the code that I am using:
public void SignPDF(string source, string target, X509Certificate2 certificate, string reason, string location, bool addVisibleSign, bool addTimeStamp, string strTSA, int qtySigns, int pageNumber)
{
try
{
Org.BouncyCastle.X509.X509Certificate vert = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(certificate);
X509CertificateParser objCP = new X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] objChain = new Org.BouncyCastle.X509.X509Certificate[] { objCP.ReadCertificate(certificate.RawData) };
IList<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(new CrlClientOnline(objChain));
PdfReader objReader = new PdfReader(source);
PdfSigner objStamper = new PdfSigner(objReader, new FileStream(target, FileMode.Create), false);
ITSAClient tsaClient = null;
IOcspClient ocspClient = null;
if (addTimeStamp)
{
OCSPVerifier ocspVerifier = new OCSPVerifier(null, null);
ocspClient = new OcspClientBouncyCastle(ocspVerifier);
tsaClient = new TSAClientBouncyCastle(strTSA);
}
PdfSignatureAppearance signatureAppearance = objStamper.GetSignatureAppearance();
signatureAppearance.SetReason(reason);
signatureAppearance.SetLocation(location);
signatureAppearance.SetPageNumber(pageNumber);
signatureAppearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION);
if (addVisibleSign && qtySigns == 1)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(36, 20, 144, 53)).SetPageNumber(pageNumber);
else if (addVisibleSign && qtySigns == 2)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(160, 20, 268, 53)).SetPageNumber(pageNumber);
else if (addVisibleSign && qtySigns == 3)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(284, 20, 392, 53)).SetPageNumber(pageNumber);
else if (addVisibleSign && qtySigns == 4)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(408, 20, 516, 53)).SetPageNumber(pageNumber);
var pk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(certificate.PrivateKey).Private;
IExternalSignature externalSignature = new PrivateKeySignature(pk, "SHA-1");
objStamper.SignDetached(externalSignature, objChain, crlList, ocspClient, tsaClient, 0, PdfSigner.CryptoStandard.CMS);
if (objReader != null)
{
objReader.Close();
}
}
catch (Exception ex)
{
result.error = true;
result.errorMessage += "Error: " + ex.Message;
}
}
谢谢!
推荐答案
我不认为该类已移植到iText 7,它只是包装类.
I do not believe that class was ported to iText 7- it is just a wrapper class.
您可以在此示例
请注意,可以在此处
是这样的:
public class X509Certificate2Signature: IExternalSignature {
private String hashAlgorithm;
private String encryptionAlgorithm;
private X509Certificate2 certificate;
public X509Certificate2Signature(X509Certificate2 certificate, String hashAlgorithm) {
if (!certificate.HasPrivateKey)
throw new ArgumentException("No private key.");
this.certificate = certificate;
this.hashAlgorithm = DigestAlgorithms.GetDigest(DigestAlgorithms.GetAllowedDigest(hashAlgorithm));
if (certificate.PrivateKey is RSACryptoServiceProvider)
encryptionAlgorithm = "RSA";
else if (certificate.PrivateKey is DSACryptoServiceProvider)
encryptionAlgorithm = "DSA";
else
throw new ArgumentException("Unknown encryption algorithm " + certificate.PrivateKey);
}
public virtual byte[] Sign(byte[] message) {
if (certificate.PrivateKey is RSACryptoServiceProvider) {
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) certificate.PrivateKey;
return rsa.SignData(message, hashAlgorithm);
}
else {
DSACryptoServiceProvider dsa = (DSACryptoServiceProvider) certificate.PrivateKey;
return dsa.SignData(message);
}
}
public virtual String GetHashAlgorithm() {
return hashAlgorithm;
}
public virtual String GetEncryptionAlgorithm() {
return encryptionAlgorithm;
}
}
将在iText 7中复制类的功能.此处在我的第一个链接中,尽管您很可能会使用signDetached()
方法来代替signDeffered()
方法.
Will replicate the class' function in iText 7. How to use the class is shown here in my first link, though you most likely will be using the signDetached()
method instead of the signDeffered()
method.
这篇关于在C#和iText 7中使用x509Certificate2创建IExternalSignature的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!