为什么在使用 iText 7.1.11 的某些 PDF 文档中数字签名不可见?
Why is the Digital Signature not visible in some PDF documents using iText 7.1.11?
我的项目使用数字证书对 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, null, null, 0, 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。
我的项目使用数字证书对 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, null, null, 0, 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。