我已经开始使用数字签名功能已有好几天了,现在我已经把所有工作都用了,现在是时候尝试在所有页面上打印邮票,但我做得不好... < / p>
尝试给出一个简短的简历,以显示我做的印章是创建PdfStamper,PdfSignatureAppearance和一个矩形,然后调用
appearance.setVisibleSignature(rectangle, 1, "SIGNATURE")
第二个参数&#34; 1&#34;上面是我想要显示标记的页码,现在可以是1,因为我试图在其他页面中显示标记创建PdfStamper,PdfSignatureAppearance和Rectangle的其他实例但是将其设置为第2页。如果它有效,我会把它放在循环中并继续更改页面参数。
但为什么它不起作用?好吧,接近结尾我调用一个MakeSignature方法,在参数中我必须通过我创建的一个外观,如果我多次调用它,签名只出现在与我传递给它的最后一个外观有关的页面上。
例如:
MakeSignature.signDetached(appearance2, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
邮票将仅显示在第一页上。
也许我可以在这里得到一些帮助???
这就是整个事情:
public String signPdfFirstTime(String src, String dest, PrivateKey pk, Certificate[] chain, String providerName, String conteudoBase64, X509Certificate cert, String alias) throws IOException, DocumentException, GeneralSecurityException
{
byte[] conteudoBinario = Base64.decode(conteudoBase64);
FileOutputStream fos = new FileOutputStream(path + File.separator + src);
fos.write(conteudoBinario);
fos.close();
File f = new File(path + File.separator + src);
FileInputStream in = new FileInputStream(f);
PdfReader reader = new PdfReader(in);
int qtypages = reader.getNumberOfPages();
FileOutputStream os = new FileOutputStream(path + File.separator + dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
Rectangle rectangle = new Rectangle(550, 50, 610, 500);// funciona vertical
appearance.setVisibleSignature(rectangle, 1, "SIGNATURE");
//Here I build a custom message...nothing relevant
StringBuilder stampMessage = new StringBuilder();
stampMessage.append("...");
stampMessage.append(alias);
stampMessage.append(" - ");
// customize appearance layer 2 to display text vertically
PdfTemplate layer2 = appearance.getLayer(2);
layer2.transform(new AffineTransform(0, 1, -1, 0, rectangle.getWidth(), 0));
Font font = new Font();
font.setColor(BaseColor.BLACK);
ColumnText ct2 = new ColumnText(layer2);
ct2.setRunDirection(PdfWriter.RUN_DIRECTION_NO_BIDI);
ct2.setSimpleColumn(new Phrase(stampMessage.toString(), font), 0, 0, rectangle.getHeight(), rectangle.getWidth(), 15, Element.ALIGN_LEFT);
ct2.go();
appearance.setCertificate(cert);
//Here starts where I tried to make a second stamp to show in the page 2
FileOutputStream fos2 = new FileOutputStream(path + File.separator + src);
fos2.write(conteudoBinario);
fos2.close();
File f2 = new File(path + File.separator + src);
FileInputStream in2 = new FileInputStream(f2);
PdfReader reader2 = new PdfReader(in2);
FileOutputStream os2 = new FileOutputStream(path + File.separator + dest);
PdfStamper stamper2 = PdfStamper.createSignature(reader2, os2, '\0');
// Creating the appearance
PdfSignatureAppearance appearance2 = stamper2.getSignatureAppearance();
Rectangle rectangle2 = new Rectangle(550, 50, 610, 500);// funciona vertical
appearance2.setVisibleSignature(rectangle2, 3, "ASSINATURA2");
//Cria a msg que aparece na estampa
StringBuilder stampMessage2 = new StringBuilder();
stampMessage2.append(" - ");
PdfTemplate layer22 = appearance.getLayer(2);
layer22.transform(new AffineTransform(0, 1, -1, 0, rectangle2.getWidth(), 0));
Font font2 = new Font();
font2.setColor(BaseColor.BLACK);
ColumnText ct22 = new ColumnText(layer22);
ct22.setRunDirection(PdfWriter.RUN_DIRECTION_NO_BIDI);
ct22.setSimpleColumn(new Phrase(stampMessage2.toString(), font2), 0, 0, rectangle2.getHeight(), rectangle2.getWidth(), 15, Element.ALIGN_LEFT);
ct22.go();
appearance2.setCertificate(cert);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, providerName);
ExternalDigest digest = new BouncyCastleDigest();
List<CrlClient> crlList = new ArrayList<CrlClient>();
crlList.add(new CrlClientOnline());
LtvVerification v = stamper.getLtvVerification();
LtvVerification v2 = stamper2.getLtvVerification();
OcspClient ocspClient = new OcspClientBouncyCastle();
String url = CertificateUtil.getCRLURL(cert);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509CRL crl = (X509CRL) cf.generateCRL(new URL(url).openStream());
System.out.println("CRL valid until: " + crl.getNextUpdate());
System.out.println("Certificate revoked: " + crl.isRevoked(chain[0]));
if (crl.isRevoked(chain[0])) {
throw new GeneralSecurityException("CERTIFICADO REVOGADO!");
}
else {
MakeSignature.processCrl(cert, crlList);
MakeSignature.signDetached(appearance2, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
os.close();
byte[] b = this.read(f);
return Base64.encodeBytes(b);
}
}
答案 0 :(得分:4)
这实际上是对可用选项的讨论......
在所有页面中打印签名标记的方式根本不同:
&#34;可视化&#34; PDF签名字段是与该字段直接关联的小部件;特别是可以点击它们打开一个签名验证对话框。与这些小部件相比,&#34;图像&#34;在第二个选项中仅仅是没有这种相关动作的图像。
这很可能是OP在他心目中的选择。特别是这是一个更好的选择,至少乍一看:
但是有许多缺点:
同一签名的多个可视化可能会对该签名的合法价值产生负面影响。
因此,Adobe多年前决定不在他们的软件中创建具有多个可视化的签名字段,参见例如文档中签名的位置可能与其法律含义有关。为此原因, 签名字段从不引用多个注释。如果多个位置与a关联 签名,意思可能变得含糊不清。
(2008年5月5日Adobe Acrobat版本9的Digital Signature Appearances白皮书)
E.g。在德国,书面签名的管辖权垂直限制签名者合法签署的文件部分,他通常不受签名下面任何书面的任何法律约束。其他法律制度也可能存在类似的管辖权。
如果签名文件中带有可视化的电子签名,则此类管辖权可能类似地持有(或者至少必须努力解释这些差异)。如果对同一签名进行多次可视化,则可能意味着只有第一个可视化文件的所有内容都被视为已签名。
(我不是律师,所以请不要考虑这次法律咨询。)
由于这些潜在的法律问题,即将发布的PDF 2.0标准中的签名字段只允许包含一个小部件。因此,根据该标准,具有多个小部件的签名可能被视为无效。
现在,Adobe Reader的签名面板已包含&#34;签名所在的页面&#34;,cf。这个屏幕截图的最后一行:
该面板上没有关联条目(具有正确的页码)的活动签名字段可能会被怀疑。
如果使用此选项,先前选项的缺点不适用或至少仅适用于较小程度。特别是如果仅通过提示指示它们是副本的图像与可视化略有不同,则最终的真实可视化可能被视为绑定签名位置。
此选项的主要缺点是,对于已签名的文档,不允许仅向内容添加图像。因此,此选项不能用于文档的第二个或第三个签名者,但OP已指示解决方案最终必须允许将文档签名给多个人。
可以考虑将这些图像添加为注释,而不是内容;对于某些类型的集成PDF签名,在签名后添加和删除注释是允许的操作。但是如果允许添加这些注释,通常也允许在签名后再次删除它们,使这些签名图像非常不稳定。
此选项没有其他选项的缺点,因为每个可视化对应于不同的数字签名。因此,最后一个保证签名者在整个文件中受法律约束。
它确实有自己的缺点:
iText允许以开箱即用的方式直接实现第二个和第三个选项。
使用iText可以实现第一个选项,但需要使用低级API和Java反射,或者稍微修补iText。
考虑到每个选项的问题,我建议不要这样做,签名内容末尾的一个签名是最不明确的签名方式。
答案 1 :(得分:1)
@mkl关于法律问题的要点非常可观。但是如果您仍然希望使用Itext api(版本5.5。*)对所有页面进行签名,那么您应该在preClose(HashMap<PdfName, Integer> exclusionSizes)
类的PdfSignatureAppearance
方法中进行一些修改,其中签名外观包含在页。
在writer.addAnnotation(sigField, pagen);
类中搜索PdfSignatureAppearance
行并替换为
for (int p = 1; p <= writer.reader.getNumberOfPages(); p++) {
writer.addAnnotation(sigField, p);
}
它将签名的引用添加到所有页面。