0

问题:我想用 iText 和 PKCS11 提供程序签署 PDF 文档(在 C# 中,Java 也可以)。这可行,但签名的 PDF 缺少几个signed attributes

  • 发行人
  • 序列号
  • 签约时间

因此,在@mkl 发表评论后,我实现了一个自定义IExternalSignatureContainer,但签名看起来无效我当前的代码:

try
{
    using (var signature = new Pkcs11Signature(libraryPath, slotId, pin, "SHA256")) // My custom PKCS11 provider
    using (var pdfReader = new PdfReader(inputFile))
    using (var result = File.Create(outputFile))
    {
        var stampingProperties = new StampingProperties();
        stampingProperties.UseAppendMode();

        // Sign the document
        var pdfSigner = new PdfSigner(pdfReader, result, stampingProperties);
        pdfSigner.SignExternalContainer(new ExternalSignature(signature), 8192);

    }
}
catch (Exception exception)
{
    throw new Exception("Unable to sign PDF file: " + exception.Message);
}
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Crypto.Digests;

namespace acme;

public class ExternalSignature : IExternalSignatureContainer
{
    private Pkcs11Signature pkcs11Signature;

    public ExternalSignature(Pkcs11Signature pkcs11Signature)
    {
        this.pkcs11Signature = pkcs11Signature;
    }

    public byte[] Sign(Stream data)
    {
        // Get the certificate chain via PKCS11
        var chain = pkcs11Signature.GetChain();

        // Create the PKCS7 container
        var pdfPkcS7 = new PdfPKCS7(null, chain, pkcs11Signature.GetHashAlgorithm(), false);
        var secondDigest = DigestAlgorithms.Digest(data, new Sha256Digest());
        var authenticatedAttributeBytes = pdfPkcS7.GetAuthenticatedAttributeBytes(secondDigest, PdfSigner.CryptoStandard.CMS, null, null);

        // Dump the authenticated attributes so we can check them via ASN1 parsing
        //File.WriteAllBytes("messageex.bin", authenticatedAttributeBytes);

        // Sign the message
        var digest = pkcs11Signature.Sign(authenticatedAttributeBytes);

        // Set the digest
        pdfPkcS7.SetExternalDigest(digest, null, pkcs11Signature.GetEncryptionAlgorithm());
        var encodedPkcS7 = pdfPkcS7.GetEncodedPKCS7(secondDigest, PdfSigner.CryptoStandard.CMS, null, null, null);

        return encodedPkcS7;
    }

    public void ModifySigningDictionary(PdfDictionary signDic)
    {
        //throw new NotImplementedException();
    }
}
4

0 回答 0