添加新签名的数字签名使旧签名无效

Digital Signature adding new signature makes old signature invalid

我正在尝试在单个 PDF 文件中添加多个数字签名。

它成功了,但是当程序添加新签名时,旧签名现在被 Adob​​e reader 检测为无效。

我只是调用了Signer.Sign()方法来做多重签名,不知道这样对不对

PDF 签名输出示例见图片

下面是我的代码

public class Signer
{
    private readonly string source;
    private readonly string destination;

    private readonly Certificate certificate;

    public Signer(string source, string destination, Certificate certificate)
    {
        this.source =  source;
        this.destination = destination;
        this.certificate = certificate;
    }

    public void Sign(Signature signature, string hashAlgorithm, PdfSigner.CryptoStandard signatureType)
    {
        PdfReader reader = new(source);
        PdfSigner signer = new(reader, new FileStream(this.destination, FileMode.Create), new StampingProperties());

        PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
        appearance.SetPageNumber(signature.PageNumber)
            .SetPageRect(signature.Bounds)
            .SetContact(signature.Contact)
            .SetLocation(signature.Location)
            .SetReason(signature.Reason)
            .SetSignatureGraphic(signature.Image)
            .SetRenderingMode(signature.RenderMode);
        signer.SetFieldName(signature.FieldName);

        IExternalSignature pks = new PrivateKeySignature(certificate.Key, hashAlgorithm);
        signer.SignDetached(pks, certificate.Chain, null, null, null, 0, signatureType);
        
        reader.Close();
    }

    public class Certificate
    {
        private readonly X509Certificate[] chain;
        private readonly ICipherParameters key;

        public X509Certificate[] Chain
        {
            get { return chain; }
        }

        public ICipherParameters Key
        {
            get { return key; }
        }

        public Certificate(string keystore, string password)
        {
            Pkcs12Store pk12 = new(new FileStream(keystore, FileMode.Open, FileAccess.Read), password.ToCharArray());
            string? alias = null;
            foreach (object a in pk12.Aliases)
            {
                alias = ((string)a);
                if (pk12.IsKeyEntry(alias))
                {
                    break;
                }
            }
            key = pk12.GetKey(alias).Key;

            X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
            chain = new X509Certificate[ce.Length];
            for (int k = 0; k < ce.Length; ++k)
            {
                chain[k] = ce[k].Certificate;
            }
        }
    }

    public class Signature
    {
        private readonly string fieldName;
        private readonly int pageNumber;
        
        public string FieldName { 
            get { return fieldName; }
        }
        public int PageNumber {
            get { return pageNumber; }
        }

        public string Contact { get; set; } = String.Empty;
        public string Reason { get; set; } = String.Empty;
        public string Location { get; set; } = String.Empty;
        public RenderingMode RenderMode { get; set; } = RenderingMode.GRAPHIC;

        public Rectangle? Bounds { get; set; }
        public ImageData? Image { get; set; }

        public Signature(string fieldName, int pageNumber)
        {
            this.fieldName = fieldName;
            this.pageNumber = pageNumber;
        }
    }
}

实施

    public static void Sign()
    {
        string source = "V06.pdf";
        string destination1 = "V06.signed1.pdf";
        string destination2 = "V06.signed2.pdf";
        Certificate certificate = new("121550.p12", "password");
        
        Signer sign1 = new(source, destination1, certificate);

        Signature signature1 = new("Sign1", 1)
        {
            RenderMode = RenderingMode.GRAPHIC,
            Contact = "000000",
            Location = "PH",
            Reason = "Valid",
            Bounds = new Rectangle(70, 148, 100, 35),
            Image = ImageDataFactory.Create("Untitled.png")
        };
        sign1.Sign(signature1, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS);



        Signer sign2 = new(destination1, destination2, certificate);
        
        Signature signature2 = new("Sign2", 1)
        {
            RenderMode = RenderingMode.GRAPHIC,
            Contact = "000000",
            Location = "PH",
            Reason = "OK",
            Bounds = new Rectangle(170, 148, 100, 35),
            Image = ImageDataFactory.Create("Untitled.png")
        };

        sign2.Sign(signature2, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS);
    }

如果您使用的是 iText 7,我想您应该尝试使用 UseAppendMode()

PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), tmp, new StampingProperties().UseAppendMode());

请参考