我试图从PDF/A-1A输入文件创建签名的PDF,输出必须保持一致性级别。
签名必须添加定制外观。
如果我沿着下面的代码行进行操作,所有的东西都在签名端工作,签名被正确显示并验证为OK。
但PDF/A一致性被不包含所需toUnicode CMAP的嵌入式字体打破。
PdfADocument pdf = ... the doc to be signed
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
PdfReader reader = pdf.getReader();
PrivateKey privateKey = ...
Provider signatureProvider = new BouncyCastleProvider();
Certificate[] signChain = ...
PdfSigner pdfSigner = new PdfSigner(reader, buffer, true);
PdfSignatureAppearance signatureAppearance = pdfSigner.getSignatureAppearance();
signatureAppearance.setReuseAppearance(false);
signatureAppearance.setPageNumber(pdf.getNumberOfPages());
pdfSigner.setFieldName("Custom Signature");
float margin = 35;
Rectangle pageSize = pdf.getLastPage().getMediaBox();
Rectangle signaturePosition = new Rectangle(pageSize.getLeft()+margin,
pageSize.getBottom()+margin,
pageSize.getWidth()-2*margin,
(pageSize.getHeight()-2*margin)/3);
// need to do this before creating any *Canvas object, else the pageRect will be null and the signature invisible
signatureAppearance.setPageRect(signaturePosition);
PdfFont regularFont = PdfFontFactory.createFont("/path/to/truetypefile-regular.ttf", "ISO-8859-1", true);
PdfFont boldFont = PdfFontFactory.createFont("/path/to/truetypefile-bold.ttf", "ISO-8859-1", true);
int fontSize = 10;
PdfFormXObject n0 = signatureAppearance.getLayer0();
PdfCanvas n0Canvas = new PdfCanvas(n0, pdfSigner.getDocument());
PdfFormXObject n2 = signatureAppearance.getLayer2();
Canvas n2Canvas = new Canvas(n2, pdfSigner.getDocument());
if(regularFont != null) {
n2Canvas.setFont(regularFont);
n0Canvas.setFontAndSize(regularFont, fontSize);
}
ImageData imageData = ImageDataFactory.create("/path/to/image.png");
Image image = new Image(imageData);
n2Canvas.add(image);
String layer2Text = ... some lines of text containing newlines and some simple markdown
String[] paragraphs = layer2text.split("\n\n");
for (String text : paragraphs) {
boolean bold = false;
if(text.startsWith("[bold]")) {
bold = true;
text = text.replaceFirst("^\\s*\\[bold\\]\\s*", "");
}
Paragraph p = new Paragraph(text);
p.setFontSize(fontSize);
if(bold) {
p.setFont(boldFont);
}
n2Canvas.add(p);
}
... pdfSigner.setCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS);
PrivateKeySignature externalSignature = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA512, signatureProvider.getName());
BouncyCastleDigest externalDigest = new BouncyCastleDigest();
pdfSigner.signDetached(externalDigest, externalSignature, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
所以我想这里少了些什么。嵌入的字体不符合PDF/A,因为它们缺少ToUnicode CMAP键。pdf tools validator的另一个错误是:“密钥编码的值是Difference,但必须是WinAnSienceODing或MacRomanEncoding。”这似乎是同样的问题。
签名本身是可以的,看起来,样式和图像都应该是正确的。只是字体似乎不太好。
违反PDF/A合规性的触发因素是此处创建字体的方式
PdfFont regularFont = PdfFontFactory.createFont("/path/to/truetypefile-regular.ttf", "ISO-8859-1", true);
PdfFont boldFont = PdfFontFactory.createFont("/path/to/truetypefile-bold.ttf", "ISO-8859-1", true);
或者甚至更具体地将编码参数"ISO-8859-1"
用于其中。
PDF/A-1规范要求:
所有非符号TrueType字体都应指定MacRomanEncoding或WinAnSiceCodeing作为字体字典中编码项的值。所有符号TrueType字体不得在字体字典中指定编码条目,其字体程序的“cmap”表格应仅包含一种编码。
使用编码参数"ISO-8859-1"
导致在字体字典中的编码项的值既不指定MacRomanEncode也不指定WinAnsiEncode。相反,该值是只包含包含显式映射的差异项的字典。
根据PDF/A验证程序的不同,这可能会导致不同的错误消息。
由于(我假设)历史原因,在字体创建过程中有几个不同的编码参数值,导致iText使用WinAnsiEncode:
"
PdfEncoding. WINANSI
(="Cp1252"
)"winansi"
(不区分大小写)"winansi编码"
(不区分大小写)OP使用了PdfName。温安斯廷。getValue()
返回与最新选项匹配的字符串。
虽然这表明iText可以用于正确签名PDF/A文档,但可能应该引入一个特定的PDFASigner
类来强制一致性。
我正在尝试使用iText(sharp,5.5.13版)创建自定义数字签名,用户可以从四个位置(顶部、底部、左侧和右侧)设置图像位置,如下所示: 刚度: 左: 顶部: 底部: 到目前为止,我试着处理签名的第0层,但我认为我做得不对,因为签名细节是在第2层设置的。 然而,这只是设置图像位置的初始草图。在下面的代码中,我加载图像并将其放入一个块中(想法取自此示例) 结果或多或少是预期的,但有两个问题:签
我有一个私人钥匙在档案里。“privatekey.pem”并且不知道如何创建谁能帮助我吗?我正在尝试使用IText7签名pdf。
我有一个场景,我需要用iText7库从pdf中获取签名信息。签名可能存在,也可能不存在。当我为没有任何数字签名的PDF实例化一个新的对象时,会出现异常 “没有相关的PdfWriter用于进行间接操作。” .如果有签名,就很好用。我不确定如何纠正这个异常。 更新为包含代码示例
使用itext v5对文档进行数字签名时。5.11 PDF/A-2b文档被破坏——这意味着它们不再作为PDF/A文档有效。违反以下规则:https://github.com/veraPDF/veraPDF-validation-profiles/wiki/PDFA-Parts-2-and-3-rules#rule-643-1 在上面的链接中,它指定摘要无效,因此我也给你一个代码段,在使用iText
我需要将一个使用iText5进行PDF签名验证/创建的Java程序移植到iText7。 旧代码显然不能按原样工作,因为iText的大部分内容都经过了重组。 我找到的所有关于如何做到这一点的例子和教程都是针对iText5的。(非常好的)白皮书也是如此。它们依赖于通过方法返回的列表,在该方法上执行所有与签名相关的操作。 在iText7中,不再具有该方法。 有人知道iText7的例子/文档吗?
对于IText5,添加数字签名相当容易。其留档的链接是:http://developers.itextpdf.com/examples/security/digital-signatures-white-paper/digital-signatures-chapter-2 有人可以在ITEXT 7中共享文档链接吗?我试过各种方法,但都没有用。在网上找不到任何链接。我可以取消签名并检查签名,但不能添