我正在将 PDF 转换为 PDF/A。我已经通过付费 PDFTools 库进行了此转换,我将转换结果放在此页面上,该页面负责验证它是否符合 PDA/A 标准https://www.pdf-online.com/osa/ validate.aspx 验证表明它符合标准。转换后,PDF 将使用 Itext 5.5.5 库进行签名,但是,如果我再次使用验证器,则 PDF/A 标准不再有效。验证器上显示的错误如下:
The name object must be UTF-8 encoded.
A device-specific color space (DeviceGray) without an appropriate output intent is used.
The font Helvetica must be embedded.
The document does not conform to the requested standard.
签名时,将有关数字签名的信息(例如印章)添加到文档中;正是由于这个原因,它不再符合标准。从消除这些错误开始,我已经使用以下代码消除了 Helvetica 字体错误:
String path = Sign.class.getResource("helvetica.ttf").toExternalForm();
FontFactory.register(path);
BaseFont base = BaseFont.createFont(path, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font font = new Font(base);
appearance.setLayer2Font(font);
但是,我并没有消除这两个错误:
The name object must be UTF-8 encoded.
A device-specific color space (DeviceGray) without an appropriate output intent is used.
The document does not conform to the requested standard.
颜色空间的错误,我尝试使用以下代码消除它,但根本没有帮助,因为当我再次进行验证时它会不断收到错误。
path = Sign.class.getResource("sRGBColorSpaceProfile.icm").toExternalForm();
ICC_Profile icc = ICC_Profile.getInstance(new FileInputStream(path));
stamper.getWriter().setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
我希望您能帮助我了解如何消除错误以使其符合 PDF/A 标准,或者是否有其他替代方法可以让我转换为 PDF/A,然后使用 Itext 5.5.5 库对其进行签名。
我很感激你能给我的帮助。谢谢
更新
这是我用来使用 Itext 5.5.5 库签署文档的代码。
String pkcs11Config = "name=NAME" + "\n" + "library=PATH";
ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11Config.getBytes());
Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);
Security.addProvider(pkcs11Provider);
KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, password);
PdfReader reader = new PdfReader(pdfInput);
FileOutputStream os = new FileOutputStream(pdfOutputTemp);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
String path = Sign.class.getResource("helvetica.ttf").toExternalForm();
FontFactory.register(path);
BaseFont base = BaseFont.createFont(path, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font font = new Font(base);
appearance.setLayer2Font(font);
path = Sign.class.getResource("sRGBColorSpaceProfile.icm").toExternalForm();
ICC_Profile icc = ICC_Profile.getInstance(new FileInputStream(path));
stamper.getWriter().setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
...
PrivateKey key = (PrivateKey) ks.getKey(alias, pass);
ExternalSignature es = new PrivateKeySignature(key, DigestAlgorithms.SHA256, null);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, chain, crlList, null, tsc, 0, CryptoStandard.CADES);
更新 2
我尝试将 PdfStamper 更改为 PdfAStamper,但是当我尝试签署文档时,它返回以下错误:
com.itextpdf.text.pdf.PdfAConformanceException: Annotation of type /Widget should have Contents key.
at com.itextpdf.text.pdf.internal.PdfA2Checker.checkAnnotation(PdfA2Checker.java:707)
at com.itextpdf.text.pdf.internal.PdfAChecker.checkPdfAConformance(PdfAChecker.java:219)
at com.itextpdf.text.pdf.internal.PdfAConformanceImp.checkPdfIsoConformance(PdfAConformanceImp.java:71)
at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3480)
at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3476)
at com.itextpdf.text.pdf.PdfAnnotation.toPdf(PdfAnnotation.java:989)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.addToObjStm(PdfWriter.java:292)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:382)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:373)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:369)
at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:843)
at com.itextpdf.text.pdf.PdfStamperImp.addAnnotation(PdfStamperImp.java:1395)
at com.itextpdf.text.pdf.PdfStamperImp.addAnnotation(PdfStamperImp.java:1408)
at com.itextpdf.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:1285)
at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:243)
更新 3
我将 itext 库从 5.5.5 更新到 5.5.13.1,效果更好。
如果我使用 PdfStamper,我可以签署文档,但是当我使用 PDF/A 验证器时,它会返回以下错误:
Validating file "DOCUMENT.pdf" for conformance level pdfa-2a
A device-specific color space (DeviceGray) without an appropriate output intent is used.
The document does not conform to the requested standard.
The document contains device-specific color spaces.
The document does not conform to the PDF/A-2a standard.
Done.
错误提示:“名称对象必须是 UTF-8 编码的。” 不再出现。
另外,我尝试使用 PdfStamper。当我尝试签署文件时,它会返回与以前不同的异常。这是新的例外:
com.itextpdf.text.pdf.PdfAConformanceException: DeviceGray shall only be used if a device independent DefaultGray colour space has been set when the DeviceGray colour space is used, or if a PDF/A OutputIntent is present.
at com.itextpdf.text.pdf.internal.PdfA2Checker.close(PdfA2Checker.java:829)
at com.itextpdf.text.pdf.PdfAStamperImp.close(PdfAStamperImp.java:227)
at com.itextpdf.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:1348)
at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:244)