itext 5 创建 PDF1.4 而不是 PDF/A

itext 5 creates PDF1.4 not PDF/A

我目前正在处理一个过时的项目,该项目已签署 PDF/A 并试图升级其依赖项。这里相关的是 co.lowagie.itext 我从 1.4 升级到 5.5.13.1。由于函数 PdfSignatureAppearance.setCrypto() 被删除,所以发生了很多变化。我在 this 中实施了修复(我在最新版本中实施了所需的 jars)问题,现在我得到了这个代码:

PdfStamper stp;
            try {

                stp = PdfStamper.createSignature(reader, fout, '[=11=]');
                PdfSignatureAppearance sap = stp.getSignatureAppearance();
                ExternalDigest digest = new BouncyCastleDigest();
                BouncyCastleProvider provider = new BouncyCastleProvider();
                Security.addProvider(provider);
                ExternalSignature signature = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA256, provider.getName());
                MakeSignature.signDetached(sap, digest, signature, certificateChain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);
                stp.close();
            }

为了比较这里是旧代码:

PdfStamper stp;
            try {
                stp = PdfStamper.createSignature(reader, fout, '[=12=]');
                PdfSignatureAppearance sap = stp.getSignatureAppearance();
                sap.setCrypto(privateKey, certificateChain, null, PdfSignatureAppearance.WINCER_SIGNED);
                stp.close();
            }

这是我的问题出现的地方。在测试期间,我注意到这个新版本将 PDF/A 转换为 PDF1.4,而旧版本没有。我对 PDF 或 PDF 签名没有经验。

PDF/A-1 是 PDF-1.4 的配置文件。因此,如果您的源 PDF 是 PDF/A-1,它一开始也是 PDF-1.4,而 iText 并没有改变它。

此外,旧的 iText 1.4 和更新的 iText 5.5.13 PdfStamper 都不是 PDF/A-aware。很可能您的测试检查由 iText 1.4 签名的 PDF 的配置文件根本没有识别出这一点。

不过,如果是 iText 5.5.13,您可能会很幸运,因为在那个版本中,iText 还提供了一个 PdfAStamper,即 PDF/A-aware(这个 class 在一个单独的不过,jar,itext-pdfa.jar).

因此,请使用 PdfAStamper 代替 PdfStamper 再试一次。如果仍然没有帮助,请在使用新旧 iText 版本签名之前和之后分享一个示例 PDF/A 代表您输入的 PDF 的文件。并提及您使用哪个程序来确定 PDF 是否为 PDF/A...

有 2 个问题阻碍代码创建有效 PDF/A

第一个问题是,我没有使用 PdfAStamper class 来标记 PDF/A 并保留其 PDF/A 有效性。

第二个问题是,签名 PDF/A 需要一个签名,其中时间戳由外部 tsa 服务器设置。

PdfStamper stp;
            try {

                stp = PdfAStamper.createSignature(reader, fout, '[=10=]',  PdfAConformanceLevel.PDF_A_1A); //<-- PdfAStamper with the PdfAConformanceLevel.
                TSAClient tsaClient = new TSAClientBouncyCastle("https://freetsa.org/tsr"); //<-- creating the TSAClient
                PdfSignatureAppearance sap = stp.getSignatureAppearance();
                ExternalDigest digest = new BouncyCastleDigest();
                BouncyCastleProvider provider = new BouncyCastleProvider();
                Security.addProvider(provider);
                ExternalSignature signature = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA256, provider.getName());
                MakeSignature.signDetached(sap, digest, signature, certificateChain, null, null, tsaClient, 0, MakeSignature.CryptoStandard.CMS); //<-- Notice "tsaClient"
                stp.close();
            }