本文介绍了如何使用iText在所有文档页面中显示数字PDF签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始研究数字签名功能已有好几天了,现在我已经完成了所有工作,现在是时候尝试在所有页面上打印邮票,但我做得不好......



试图给出快速简历,以显示我做的印章是创建PdfStamper,PdfSignatureAppearance和一个矩形,然后调用

  appearance.setVisibleSignature(rectangle,1,SIGNATURE)

上面的第二个参数1是我想要显示标记的页码,现在可以是1,因为我试图在其他页面中显示标记正在创建PdfStamper的其他实例,PdfSignatureAppearance和一个矩形,但将其设置为第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();

文件f =新文件(路径+ 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');
//创建外观
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
Rectangle rectangle = new Rectangle(550,50,610,500); // funciona vertical
appearance.setVisibleSignature(rectangle,1,SIGNATURE);

//这里我构建了一个自定义消息......没什么相关的
StringBuilder stampMessage = new StringBuilder();
stampMessage.append(...);
stampMessage.append(别名);
stampMessage.append( - );
//自定义外观图层2以垂直显示文本
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);

//这里开始我试图在页面中显示第二个标记2
FileOutputStream fos2 = new FileOutputStream(path + File.separator + src);
fos2.write(conteudoBinario);
fos2.close();
文件f2 =新文件(路径+ 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');
//创建外观
PdfSignatureAppearance appearance2 = stamper2.getSignatureAppearance();

矩形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);

//创建签名
ExternalSignature pks = new PrivateKeySignature(pk,DigestAlgorithms.SHA256,providerName);
ExternalDigest digest = new BouncyCastleDigest();
列表< 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有效期至:+ crl.getNextUpdate());
System.out.println(证书已撤销:+ crl.isRevoked(chain [0]));

if(crl.isRevoked(chain [0])){

抛出新的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);
返回Base64.encodeBytes(b);
}
}


解决方案

这实际上是对可用选项的讨论...



打印签名的方法根本不同em>所有页面中的标记:




  • 创建一个包含多个可视化的单一签名字段,每页一个。

  • 在单个页面上创建单个可视化字段,例如最后一个文档页面,并在所有其他页面上创建具有相同内容的图像。

  • 每页创建一个签名字段,每个页面上都有一个可视化文件。



PDF签名字段的可视化是与该字段直接关联的小部件;特别是可以点击它们打开一个签名验证对话框。与这些小部件相比,第二个选项中的图像仅仅是没有相关动作的图像。



单个签名,多个可视化



这很可能是OP在他心目中的选择。特别是这是一个更好的选择,至少乍一看:




  • 每个页面上签名图像处于活动状态并允许打开签名验证对话框;

  • 但仍然只需要创建一个数字签名,这意味着


    • 签名上只有一个条目Adobe Reader左侧的面板,

    • 只有一个要验证的签名容器(因此,没有明确的验证结果),而

    • 只使用一次私钥,因此PIN不需要多次输入,并且如果按签名付费签名服务只需要支付一个签名事件。




但是有许多缺点:




  • 同一签名的多个可视化可能会对该签名的合法价值产生负面影响。



    Adob​​e因此决定几年前没有用multi创建签名字段在他们的软件中进行可视化,参见例如

    E.g. in Germany jurisdiction concerning written signatures vertically confines the part of the document the signer has legally signed, he generally is not legally bound by anything written below the signature. Similar jurisdiction may exist in other legal systems, too.

    In case of electronic signatures with visualizations in the signed documents, such jurisdiction might hold analogously (or one at least has to make quite an effort to explain the differences). In case of multiple visualization of the same signature this might mean that only everything up to the first visualization is considered signed.

    (I am not a lawyer, so please do not consider this legal consultation.)

  • Because of such potential legal issues signature fields in the upcoming PDF 2.0 standard will only be allowed to have a single widget. Thus, signatures with multiple widgets likely will be considered invalid according to that standard.

  • Already now the signature panel of Adobe Reader contains "the page the signature is on", cf. the last line of this screen shot:

    Active signature fields without an associated entry (with the correct page number) on that panel might be doubted outright.

Single signature, single visualization on last page, inactive images on the other pages

In case of using this option, the disadvantages of the prior option do not apply or at least only to a lesser degree. In particular if the mere images slightly differ from the visualization by a hint indicating that they are copies, the final, true visualization will likely be considered the binding signature location.

The major disadvantage of this option, though, is that adding mere images to the content is not allowed for already signed documents. Thus, this option cannot be used for the second or third signer of a document, but the OP has indicated that the solution will eventually have to allow the documents to be signed to more than one person.

One can consider adding those images as annotations, not as content; for certain types of integrated PDF signatures adding and removing annotations after signing is an allowed operation. But if adding those annotations was allowed, usually removing them again after signing is allowed, too, making those signature images quite volatile.

Multiple signatures (one per page) with a single visualization each

This option does not have the disadvantages of the other options as each visualization corresponds to a different digital signature. Thus, the final one guarantees that the signer is legally bound by the whole document.

It does have disadvantages of its own, though:

  • During verification all these signatures will be verified. This might mean high resource requirements, and even worse ambiguous results (if some verifications fail and some succeed).
  • The Adobe Reader signature panel is flooded with entries.
  • The private key is used multiple times which in case of pay-per-signatures signing services is expensive and in case of SSCDs (in particular smart cards or tokens) might require entering the PIN multiple times and also take quite some time

Implementing the options

iText allows implementing the second and third option in a fairly straight-forward manner out-of-the-box.

Implementing the first option is possible with iText but requires the use of low-level APIs and Java reflection or alternatively patching iText a bit.


Considering the problems of each option, though, I'd advice against doing this at all, one signature right at the end of the content to sign is the least ambiguous way to sign.

这篇关于如何使用iText在所有文档页面中显示数字PDF签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 12:30