为什么在使用iText 7.1.11的某些PDF文档中看不到数字签名?

问题描述

我的项目使用数字证书对PDF文档进行数字签名,并在文档的左下方显示签名。到目前为止,它一直运行良好,虽然有些文档已经过数字签名,但可以识别出可见的矩形,但它并未显示。有人可以帮忙吗,我留下了一段处理数字签名的代码Here我留下了PDF文档中数字签名的截图,并在文档的左下角显示了它。

示例

在此link中,我共享了有关该问题的示例pdf文档,如果没有它,我将在下面详细介绍它们:

  • ok_unsigned.pdf文件:该文件在通过我的项目时被正确签名,成为ok_signed.pdf文件(这是目前的规范)
  • ok_signed.pdf文件:这是经过数字签名的ok_unsigned.pdf文件,这是成功的案例
  • bad_unsigned.pdf文件:这是一个空白文档,当进行数字签名(bad_signed.pdf)时,出现相关问题
  • bad_signed.pdf文件:这是一个有问题的文档,已经过数字签名,但看不到签名字段。

代码

        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,SUBFILTER);
            System.out.println("SIGNED");
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }```

解决方法

@mkl表示您的坐标可能在页面可见区域之外,因为并非所有PDF页面的左下角都位于(0,0)。

尝试像这样创建签名矩形:

Rectangle rect = new Rectangle(
    yourPageCropBoxLowerLeftX + 10,yourPageCropBoxLowerLeftY + 10,yourPageCropBoxLowerLeftX + 10 + yourSignatureWidth,yourPageCropBoxLowerLeftY + 10 + yourSignatureHeight);

由于我不熟悉iText API,您只需要查看如何读取页面的裁剪框坐标(左下角)即可。