我正在测试 iText 7.1.2.0 库来签署 pdf 文件,在 C# 项目中使用数字证书或智能卡 (X509Certificate2)。但是当我尝试创建 IExternalSignature 时出现此错误。
根据找到的文档(here、here 和 here),实现此过程的方法是使用允许从数字证书中提取主键的 BouncyCaSTLe 库,但是,它给了我一个错误,我找不到另一种方法来做到这一点。 在文档 ( here ) 中,它们是从 .pfx 文件创建的,但对于这种情况,我需要直接从读卡器中的证书中获取主 key 。在以前的 iText 版本中,允许使用以下命令创建:
IExternalSignature externalSignature = new X509Certificate2Signature(Certificate, "SHA-1");
但在版本 7 中它不再可用,而且在文档中我也看不到如何操作。
有人使用过 iText 7 并且能够使用知道创建 IExternalSignature 的正确方法的 X509Certificate2 进行签名吗?
这是我正在使用的代码:
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 - 它只是一个包装类。
您可以在 this example 中查看如何创建自定义 IExternalSignatureContainer
请注意,可以找到 iText 5 X509Certificate2Signature 的来源 here
所以像这样:
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 中复制该类的功能。显示如何使用该类 here在我的第一个链接中,尽管您很可能会使用 signDetached()
方法而不是 signDeffered()
方法。
关于c# - 在 C# 和 iText 7 中使用 x509Certificate2 创建 IExternalSignature,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50627483/