为什么在使用 iText 7.1.11 时,某些 PDF 文档中的数字签名不可见?

huangapple go评论71阅读模式
英文:

Why is the Digital Signature not visible in some PDF documents using iText 7.1.11?

问题

这是我的项目,使用数字证书对PDF文档进行数字签名,并将签名显示在文档的左下角。一直以来都运行良好,但现在出现了一些问题:有些文档进行了数字签名,但签名没有显示,尽管可以识别出可见签名的矩形区域。是否有人可以帮助解决这个问题?我在这里留下一个处理数字签名的代码片段。

这里是数字签名在PDF文档中的屏幕截图,我在文档的左下角显示它。

示例

在这个链接中,我分享了出现问题的示例PDF文档和没有问题的示例文档,我将在下面详细介绍它们:

  • ok_unsigned.pdf 文件:通过我的项目时,它被正确签名,生成 ok_signed.pdf 文件(迄今为止都是正常的)。
  • ok_signed.pdf 文件:数字签名的 ok_unsigned.pdf 文件,这是一个成功的案例。
  • bad_unsigned.pdf 文件:这是一个空白文档,当进行数字签名(bad_signed.pdf)时,出现了问题。
  • bad_signed.pdf 文件:这是一个出现问题的文档,进行了数字签名,但在视觉上看不到签名字段。

代码

public static void sign(String src, String dest, String keystore, char[] password) {
    try {
        BouncyCastleProvider providerBC = new BouncyCastleProvider();
        Security.addProvider(providerBC);

        KeyStore ks = KeyStore.getInstance("pkcs12");
        ks.load(new FileInputStream(keystore), password);
        String alias = ks.aliases().nextElement();
        Certificate[] chain = ks.getCertificateChain(alias);
        PrivateKey pk = (PrivateKey) ks.getKey(alias, password);

        PdfReader reader = new PdfReader(src);
        FileOutputStream fos = new FileOutputStream(new File(dest));
        PdfSigner signer = new PdfSigner(reader, fos, new StampingProperties());
        Rectangle rect = new Rectangle(10, 10, 150, 50);
        PdfSignatureAppearance appearance = signer.getSignatureAppearance();

        appearance.setPageRect(rect)
                .setCertificate(chain[0])
                .setReasonCaption("")
                .setLocationCaption("")
                .setSignatureCreator("SignerJAGC - iText 7.1.11")
                .setPageNumber(1);
        signer.setFieldName("Banca en Línea - Envío de Documentos");
        signer.setSignDate(new GregorianCalendar());
        signer.setCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED);

        IExternalDigest digest = new BouncyCastleDigest();
        IExternalSignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, providerBC.getName());

        signer.signDetached(digest, signature, chain, null, null, null, 0, SUBFILTER);
        System.out.println("SIGNED");
    } catch (Exception ex) {
        System.err.println(ex.getMessage());
    }
}
英文:

My project digitally signs PDF documents using a digital certificate and displays the signature at the bottom left of the document. It had always worked well until now, there are some documents that are digitally signed but it is not shown although it is recognized that the rectangle where it is visible is. Could someone help with this, I leave a snippet that handles the digital signature.
Here I leave a screenshot of how the digital signature is in a PDF document, I show it in the lower left corner of the document.

EXAMPLES

In this link I have shared example pdf documents of the problem and without it, I will detail them below:

  • ok_unsigned.pdf file: it is a document that when passing through my project is signed well, becoming the ok_signed.pdf file (this is the norm so far)
  • ok_signed.pdf file: it is the digitally signed ok_unsigned.pdf file, it is a case of success
  • bad_unsigned.pdf file: it is a blank document that when digitally signed (bad_signed.pdf) the issue in question appears
  • bad_signed.pdf file: it is a document with the issue in question, digitally signed but without visually seeing the signature field.

CODE

        try {
BouncyCastleProvider providerBC = new BouncyCastleProvider();
Security.addProvider(providerBC);
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream(keystore), password);
String alias = ks.aliases().nextElement();
Certificate[] chain = ks.getCertificateChain(alias);
PrivateKey pk = (PrivateKey) ks.getKey(alias, password);
PdfReader reader = new PdfReader(src);
FileOutputStream fos = new FileOutputStream(new File(dest));
PdfSigner signer = new PdfSigner(reader, fos, new StampingProperties());
Rectangle rect = new Rectangle(10, 10, 150, 50);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance.setPageRect(rect)
.setCertificate(chain[0])
.setReasonCaption("")
.setLocationCaption("")
.setSignatureCreator("SignerJAGC - iText 7.1.11")
.setPageNumber(1);
signer.setFieldName("Banca en Línea - Envío de Documentos");
signer.setSignDate(new GregorianCalendar());
signer.setCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED);
IExternalDigest digest = new BouncyCastleDigest();
IExternalSignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, providerBC.getName());
signer.signDetached(digest, signature, chain, null, null, null, 0, SUBFILTER);
System.out.println("SIGNED");
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}```
</details>
# 答案1
**得分**: 2
如@mkl所说,您的坐标可能位于页面可见区域之外,因为并非所有PDF页面的左下角都在(0, 0)处。
尝试按照以下方式创建签名矩形:
Rectangle rect = new Rectangle(
yourPageCropBoxLowerLeftX + 10, 
yourPageCropBoxLowerLeftY + 10, 
yourPageCropBoxLowerLeftX + 10 + yourSignatureWidth, 
yourPageCropBoxLowerLeftY + 10 + yourSignatureHeight);
您只需了解如何读取页面的裁剪框坐标,即左下角,因为我对iText API不太熟悉。
<details>
<summary>英文:</summary>
As @mkl said your coordinates might be outside of the page visible area as not all PDF pages have the bottom left corner at (0, 0).
Try creating the signature rectangle like this:
Rectangle rect = new Rectangle(
yourPageCropBoxLowerLeftX + 10, 
yourPageCropBoxLowerLeftY + 10, 
yourPageCropBoxLowerLeftX + 10 + yourSignatureWidth, 
yourPageCropBoxLowerLeftY + 10 + yourSignatureHeight);
You just have to see how you can read the page&#39;s crop box coordinates, the lower left corner, as I&#39;m not familiar with iText API.  
</details>

huangapple
  • 本文由 发表于 2020年9月2日 21:28:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63706615.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定