Stamper.addSignature("My Signature", 1, 20f, 10f, 100f, 100f);
OP希望将文档内签名可视化附加到现有签名。
首先,这显然是不允许的,如果您的文件已经认证,不允许更改
然而,令人惊讶的是,它似乎确实允许签名但未经认证的文档(示例文件就是我使用的)。
Stamper.addSignature("My Signature", 1, 20f, 10f, 100f, 100f);
使用iText 5.x,这可以使用通用的表单字段操作API来完成:
PdfReader pdfReader = new PdfReader(resource);
PdfStamper pdfStamper = new PdfStamper(pdfReader, result, '\0', true);
AcroFields acroFields = pdfStamper.getAcroFields();
for (String signatureName : acroFields.getSignatureNames())
{
Item field = acroFields.getFieldItem(signatureName);
field.writeToAll(PdfName.RECT, new PdfArray(new int[]{100,100,200,200}), Item.WRITE_WIDGET);
field.markUsed(acroFields, Item.WRITE_WIDGET);
PdfAppearance appearance = PdfAppearance.createAppearance(pdfStamper.getWriter(), 100, 100);
appearance.setColorStroke(BaseColor.RED);
appearance.moveTo(0, 0);
appearance.lineTo(99, 99);
appearance.moveTo(0, 99);
appearance.lineTo(99, 0);
appearance.stroke();
PdfDictionary appDict = new PdfDictionary();
appDict.put(PdfName.N, appearance.getIndirectReference());
field.writeToAll(PdfName.AP, appDict, Item.WRITE_WIDGET);
}
pdfStamper.close();
(ChangeSignatureAppearance.java methodTestChangeParamese
)
此代码为每个集成的PDF签名创建一个新的签名外观,在本例中是一个位于100、100和大小为100x100的红十字,但您可以在那里创建任何您喜欢的外观。
为此,您只需要稍微修改一下上面的代码:
PdfReader pdfReader = new PdfReader(resource);
PdfStamper pdfStamper = new PdfStamper(pdfReader, result, '\0', true);
AcroFields acroFields = pdfStamper.getAcroFields();
for (String signatureName : acroFields.getSignatureNames())
{
PdfPKCS7 pkcs7 = acroFields.verifySignature(signatureName);
X509Certificate signerCert = (X509Certificate) pkcs7.getSigningCertificate();
String signerName = CertificateInfo.getSubjectFields(signerCert).getField("CN");
Item field = acroFields.getFieldItem(signatureName);
field.writeToAll(PdfName.RECT, new PdfArray(new int[]{100,100,200,200}), Item.WRITE_WIDGET);
field.markUsed(acroFields, Item.WRITE_WIDGET);
PdfAppearance appearance = PdfAppearance.createAppearance(pdfStamper.getWriter(), 100, 100);
ColumnText columnText = new ColumnText(appearance);
Chunk chunk = new Chunk();
chunk.setSkew(0, 12);
chunk.append("Signed by:");
columnText.addElement(new Paragraph(chunk));
chunk = new Chunk();
chunk.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, 1, BaseColor.BLACK);
chunk.append(signerName);
columnText.addElement(new Paragraph(chunk));
columnText.setSimpleColumn(0, 0, 100, 100);
columnText.go();
PdfDictionary appDict = new PdfDictionary();
appDict.put(PdfName.N, appearance.getIndirectReference());
field.writeToAll(PdfName.AP, appDict, Item.WRITE_WIDGET);
}
pdfStamper.close();
(ChangeSignatureAppearance.java方法TestChangeAppearancesWithName
)
对于示例文档,BouncyCastle必须注册为security Provider。
try ( PdfReader pdfReader = new PdfReader(resource);
PdfWriter pdfWriter = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter, new StampingProperties().useAppendMode()))
{
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, false);
for (String name : signatureUtil.getSignatureNames())
{
PdfFormField field = acroForm.getField(name);
field.setModified();
for (PdfWidgetAnnotation pdfWidgetAnnotation : field.getWidgets())
{
pdfWidgetAnnotation.setRectangle(new PdfArray(new int[]{100, 100, 200, 200}));
PdfFormXObject form = new PdfFormXObject(new Rectangle(100, 100));
PdfCanvas canvas = new PdfCanvas(form, pdfDocument);
canvas.setStrokeColor(Color.RED);
canvas.moveTo(0, 0);
canvas.lineTo(99, 99);
canvas.moveTo(0, 99);
canvas.lineTo(99, 0);
canvas.stroke();
pdfWidgetAnnotation.setNormalAppearance(form.getPdfObject());
}
}
}
与上面的iText5代码相同的警告适用:
注意:这段代码假设隐形签名已经与某个文档页面相关联。
带有主题名称的变体如下所示:
try ( PdfReader pdfReader = new PdfReader(resource);
PdfWriter pdfWriter = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter, new StampingProperties().useAppendMode()))
{
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, false);
for (String name : signatureUtil.getSignatureNames())
{
PdfPKCS7 pkcs7 = signatureUtil.verifySignature(name);
X509Certificate signerCert = (X509Certificate) pkcs7.getSigningCertificate();
String signerName = CertificateInfo.getSubjectFields(signerCert).getField("CN");
PdfFormField field = acroForm.getField(name);
field.setModified();
for (PdfWidgetAnnotation pdfWidgetAnnotation : field.getWidgets())
{
pdfWidgetAnnotation.setRectangle(new PdfArray(new int[]{100, 100, 200, 200}));
PdfFormXObject form = new PdfFormXObject(new Rectangle(100, 100));
Canvas canvas = new Canvas(form, pdfDocument);
canvas.add(new Paragraph().setItalic().add("Signed by:"));
canvas.add(new Paragraph().setBold().add(signerName));
pdfWidgetAnnotation.setNormalAppearance(form.getPdfObject());
}
}
}
关于未签名更改的警告是正确的,但再次签名后,甚至该警告也消失了:
具有签名者名称的变体如下所示:
该行动在评论中问道
try ( PdfReader pdfReader = new PdfReader(resource);
PdfWriter pdfWriter = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter, new StampingProperties().useAppendMode()))
{
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, false);
for (String name : signatureUtil.getSignatureNames())
{
PdfPKCS7 pkcs7 = signatureUtil.verifySignature(name);
X509Certificate signerCert = (X509Certificate) pkcs7.getSigningCertificate();
String signerName = CertificateInfo.getSubjectFields(signerCert).getField("CN");
PdfFormField field = acroForm.getField(name);
field.setModified();
Rectangle rectangle = new Rectangle(100, 100);
PdfFormXObject form = new PdfFormXObject(rectangle);
Canvas canvas = new Canvas(form, pdfDocument);
canvas.add(new Paragraph().setItalic().add("Signed by:"));
canvas.add(new Paragraph().setBold().add(signerName));
for (PdfWidgetAnnotation pdfWidgetAnnotation : field.getWidgets())
{
PdfDictionary pageObject = pdfWidgetAnnotation.getPageObject();
PdfPage page = pdfDocument.getPage(pageObject);
page.removeAnnotation(pdfWidgetAnnotation);
pdfWidgetAnnotation.releaseFormFieldFromWidgetAnnotation();
}
for (int pageNumber = 1; pageNumber <= pdfDocument.getNumberOfPages(); pageNumber++)
{
PdfPage pdfPage = pdfDocument.getPage(pageNumber);
PdfWidgetAnnotation pdfWidgetAnnotation = new PdfWidgetAnnotation(rectangle);
pdfWidgetAnnotation.setNormalAppearance(form.getPdfObject());
pdfWidgetAnnotation.setPage(pdfPage);
field.addKid(pdfWidgetAnnotation);
pdfPage.addAnnotation(pdfWidgetAnnotation);
}
}
}
这首先删除签名字段的任何现有注释,然后向所有字段添加新注释。
就像上面一样,这会出现一个关于未签名更改的警告,毕竟这是真的。
顺便说一句,如果在一个页面上使用带有可视化的签名文档,并更改上面的代码以不删除原始注释,则可以很容易地将该注释的副本添加到所有页面,而当前的Adobe Acrobat Reader甚至不会显示警告!检查签名文档中更改的阅读器代码确实很奇怪...
问题内容: 在PDFBox 2.x中,我将字典放入签名字段: 然后,我签名区域: 除了我在Adobe Acrobat中打开签名的文档时,它抱怨文档的内容已更改,一切看起来都还不错。如果我不添加字典,一切都很好。 任何人都知道哪里错了吗? 问题答案: 问题在于PDFBox签名没有考虑 Lock 字典。 根据ISO 32000-1(以及类似的ISO 32000-2): 12.8.2.4 FieldMD
我正在尝试向现有的数字签名pdf(认证签名)中添加一个空签名字段。 我有一个工作流,其中许多用户将签署该文档(批准签名),该文档创建时带有“n”个空签名字段,每个用户一个,我们的应用程序首先应用一个不可见的认证签名,然后每个用户可以在各自的字段中签署该文档,但由于工作流中意外的更改,其他用户可能希望签名,因此,我们希望添加相应的空签名字段,然后应用签名。 我试图将空字段(带有单元格事件的表)添加到
我有一个简单的签名方法来签署工作正常的PDF文档,它使用显示名称、位置、日期和原因的默认戳记来签署文档。 现在我的经理问我是否可以在上面再添加一个字段。让我们假设这是一个“电子邮件”字段,因为我还没有被告知他们想要什么。 我试着搜索并应用我找到的一些东西,但没有任何效果。 此外,有人问我是否可以删除/隐藏这4个默认字段的标签(日期、原因等...),我无法管理这样做,也找不到任何关于它的东西,我不知
我的手被https、ssl、PKI之类的东西弄得脏兮兮的。对于自签名证书,有一点我不太理解。假设我想创建一个自签名证书,并在我们想要建立安全连接时将其发送给我的朋友。 所以步骤是: 创建一个私钥。 创建一个公钥。 用我的公钥在证书上签名。 因此,当我的朋友得到我的证书时,他必须验证他得到的证书是我的,他需要解密数字签名。但为了解密和验证他必须拥有我的私钥。所以,我有点困惑。
印度的《公司法》有一些变化。其中值得注意的是,有一项规定,如果公司进行了数字签名,则可以以电子形式维护其登记册。以下几点让我感到困惑: > 记录一旦以数字方式标注日期和签名,不得编辑或更改; 记录应能够根据法案的规定或根据法案制定的规则进行更新,更新日期应能够记录在每次更新中。 想象一下,我们正在对PDF中的表进行数字签名。如果表中最初有2行,并且用户对pdf进行数字签名。现在,我们在pdf中再添
我必须创建一个PDF文件,其中我使用PDFmake来实现这一点。但PDFmake不具备在文档中添加签名字段的功能。 因此,我打开了一个带有签名字段的示例PDF,并复制了包含签名字段名称的对象: