pdf - 使用 itextsharp 5.5.13.2 和 SHA-256 签署 PDF 时出现“错误未指定算法”
问题描述
早上好,我正在尝试使用 ItextSharp 5.5.13.2 和 SHA-256 对 PDF 文档进行签名以进行签名过程,但在签名时我收到错误“指定的算法无效”。当我使用带有 .NetFramework 4.7.2 的 SHA-1 来签署 PDF 时,不会发生此错误,下一种方法是我用来签署 PDF 的方法。
public void SignPDF(string PathSourceDoc, string PathTargetDoc, X509Certificate2 certificate, string pathLogo)
{
using (PdfReader reader = new PdfReader(PathSourceDoc))
using (var writer = new FileStream(PathTargetDoc, FileMode.Create, FileAccess.Write))
using (var stamper = PdfStamper.CreateSignature(reader, writer, '\0', null, true))
{
var signature = stamper.SignatureAppearance;
signature.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
signature.Reason = "My Reason";
signature.Location = "My Location";
signature.SignDate = DateTime.Now;
signature.Acro6Layers = true;
PdfSignature objSignature = new PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
objSignature.Date = new PdfDate(signature.SignDate);
signature.CryptoDictionary = objSignature;
var bcCert = DotNetUtilities.FromX509Certificate(certificate);
string name = CertificateInfo.GetSubjectFields(bcCert).GetField("CN");
string industry = CertificateInfo.GetSubjectFields(bcCert).GetField("O");
string position = CertificateInfo.GetSubjectFields(bcCert).GetField("T");
DateTime date = DateTime.Now;
signature.Layer2Text = "Digital Signed by: " + name + "\n" +
"Reason: " + "My Reason" + "\n" +
"Date: " + date;
signature.Layer2Font = new Font(iTextSharp.text.Font.FontFamily.TIMES_ROMAN, 8);
Image img = Image.GetInstance(pathLogo);
signature.SignatureGraphic = img;
signature.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION;
Rectangle rect = new Rectangle(50, 50, 300, 110);
signature.SetVisibleSignature(rect, 1, null);
var standard = CryptoStandard.CADES;
/*I tried this way but I get an error of type Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'The requested operation is not supported.'*/
X509Certificate cert = certificate;
X509Certificate2 signatureCert = new X509Certificate2(cert);
var pk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(signatureCert.PrivateKey).Private;// the error is generated in this line (Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'The requested operation is not supported.').
IExternalSignature es = new PrivateKeySignature(pk, "SHA-256");
/****************************************************************************************************************************************************************/
X509Certificate2Signature externalSignature = new X509Certificate2Signature(certificate, DigestAlgorithms.SHA1); /*throws an exception on this line of type "System.ArgumentException: 'Unknown encryption algorithm System.Security.Cryptography.RSACng'"
* when using .NET Core 3.1. this always happens, it doesn't matter if I use sha1 or use any other algorithm, it always generates error*/
MakeSignature.SignDetached(signature, externalSignature, new[] { bcCert }, null, null, null, 0, standard);
}
}
该方法接收我需要签名的 PDF 的路径、签名时将创建的 pdf 的路径、证书和用于在签名中显示图像的徽标路径作为输入参数。实际上我不知道我做错了什么,因为我一直在研究相关问题,它应该适用于 SHA-1 和 SHA-256 以及 .NetFramework。
然后我将项目迁移到 .NetCore 3.1 以尝试解决问题,但我得到了一个新错误(代码中已对此进行了注释)。我的目标是使用 .NetCore 并允许我使用 sha256 签署 pdf。为了使程序正常工作,我修改 SignPdf 方法没有问题。任何贡献或信息链接表示赞赏。谢谢你的帮助。
Psdt:这是stacktrace如下...
解决方案
显然,使用的 Microsoft Crypto APIX509Certificate2Signature
不支持 SHA-256。
您使用X509Certificate2Signature
实例作为 的IExternalSignature
参数MakeSignature.SignDetached
。
如果PrivateKey
您的X509Certificate2
是 a RSACryptoServiceProvider
(您的证书似乎就是这种情况),X509Certificate2Signature.Sign
请致电
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey;
return rsa.SignData(message, hashAlgorithm);
RSACryptoServiceProvider.SignData
起初显然确实支持"SHA256"
,因为在将执行转发给SignHash
它之前必须计算要签名的哈希值。
RSACryptoServiceProvider.SignHash
但是,根据有关该方法的Microsoft 文档,它不支持 SHA-256 :
评论
此方法创建使用 VerifyHash 方法验证的数字签名。
有效的哈希算法是 SHA1 和 MD5。算法标识符可以通过使用 MapNameToOID 方法从哈希名称派生。
由于 SHA1 和 MD5 的冲突问题,Microsoft 建议使用基于 SHA256 或更好的安全模型。
(查看时间:2021-06-24,11:07)
因此,您会收到“指定的算法无效”错误。
因此,本质上,不应再基于IExternalSignature
RSA 签名的实现RSACryptoServiceProvider
。
也许这就是为什么X509Certificate2Signature
没有移植到 iText 版本 7...
另一种方法可能是检查 是否PrivateKey
是RSACng
第一个,在这种情况下将其用作RSACng
. RSA 算法的这种下一代密码学 (CNG)实现应该支持更好的散列算法......
推荐阅读
- excel - 如何使用excel宏在单元格中写入工作簿名称
- symfony - Symfony\Component\Console\Exception\LogicException 在 php bin/console server:run
- powershell - 向函数添加计数过程
- excel - 如何在Excel VBA中使用#复制超链接
- yocto - 如何让复杂的非 Yocto 基于 makefile 的项目在 Yocto 层中进行交叉编译?
- c# - 不知道类型的反序列化
- node.js - Nodemailer:如何发送带有 icalEvent 和附件的电子邮件
- sql - 计算一个表中的行并在另一个表中使用该变量(联合)
- c - 带有函数调用 arg 的 printf() 有时不正确
- spring-boot - 从 Spring Boot POM 文件中删除私有 docker 注册表凭据