You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用iText 8.0.2的ECDSA证书签名PDF,Adobe Reader提示文档已篡改

使用iText 8.0.2结合ECDSA(SHA-256)证书签名PDF后Adobe Reader提示签名无效的问题

我使用iText 8.0.2结合ECDSA(SHA-256)证书对PDF文档进行签名,但Adobe Reader提示签名无效,原因显示“文档自签名后已被更改或损坏”。由于对数字签名不熟悉,无法定位问题所在,恳请专业人士指导。

我已移除TSA、LTV等附加功能,尝试过OpenSSL测试证书及w3.org测试PDF,问题仍存在。

签名代码如下:

using iText.Kernel.Pdf;
using iText.Signatures;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace PdfSignTest
{   
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Usage: PdfSignTest.exe pdfFilePath pfxFilePath");
                Console.WriteLine(" - pdfFilePath: path of an unsigned pdf file which will be signed");
                Console.WriteLine(" - pfxFilePath: path of a pfx file containing the full certificate chain");
                Console.ReadKey();
                return;
            }

            string srcPath = args[0];
            string cerPath = args[1];
            string dstPath = srcPath.Replace(".pdf", ".signed.at." + DateTime.Now.ToString("HH-mm-ss") + ".pdf");

            var signed = SignPdfECC(srcPath, cerPath);
            File.WriteAllBytes(dstPath, signed);

            Console.WriteLine(string.Format("File {0} successfully signed and saved as {1}.", srcPath, dstPath));
            Console.ReadKey();
        }

        private static byte[] SignPdfECC(string unsignedPdfPath, string certificatePfxPath)
        {
            byte[] certificatePfx = File.ReadAllBytes(certificatePfxPath);

            using (PdfReader reader = new PdfReader(unsignedPdfPath))
            using (MemoryStream mem = new MemoryStream())
            {
                PdfSigner signer = new PdfSigner(reader, mem, new StampingProperties().UseAppendMode());
                X509Certificate cert = new X509Certificate(certificatePfx, "password", X509KeyStorageFlags.Exportable);
                X509Certificate2 signatureCert = new X509Certificate2(cert);
                ECDsa pk = signatureCert.GetECDsaPrivateKey();
                IExternalSignature signature = new EcdsaSignature(pk, DigestAlgorithms.SHA256);
                iText.Bouncycastle.X509.X509CertificateBC[] chain = new iText.Bouncycastle.X509.X509CertificateBC[] { new iText.Bouncycastle.X509.X509CertificateBC(new Org.BouncyCastle.X509.X509Certificate(signatureCert.GetRawCertData())) };
                signer.SignDetached(signature, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
                return mem.ToArray();
            }
        }
    }

    public class EcdsaSignature : IExternalSignature
    {
        private readonly string _encryptionAlgorithm;
        private readonly string _hashAlgorithm;
        private readonly ECDsa _pk;

        public EcdsaSignature(ECDsa pk, string hashAlgorithm)
        {
            _pk = pk;
            _hashAlgorithm = DigestAlgorithms.GetDigest(DigestAlgorithms.GetAllowedDigest(hashAlgorithm));
            _encryptionAlgorithm = "ECDSA";
        }

        public string GetDigestAlgorithmName()
        {
            return "SHA-256";
        }

        public virtual string GetEncryptionAlgorithm()
        {
            return _encryptionAlgorithm;
        }

        public virtual string GetHashAlgorithm()
        {
            return _hashAlgorithm;
        }

        public string GetSignatureAlgorithmName()
        {
            return "ECDSA";
        }

        public ISignatureMechanismParams GetSignatureMechanismParameters()
        {
            return null;
        }

        public virtual byte[] Sign(byte[] message)
        {
            return _pk.SignData(message, new HashAlgorithmName(_hashAlgorithm));
        }
    }
}

内容的提问来源于stack exchange,提问作者Imre Tessényi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 14:39:51