使用iText的Java PDF数字签名可见,但不可打印

时间:2018-11-07 15:53:55

标签: java pdf itext certificate digital-signature

我正在使用iText的方法对具有数字证书的PDF进行签名,并使用PdfSignatureAppearance生成了在文档中可见的签名,但是我希望不显示可见签名。我看到PdfAnnotation类中有类似的东西,您可以在其中添加一个标志。有什么办法可以使用数字签名吗? 我的代码:

PdfStamper stp = null;
try {
    PdfReader reader = new PdfReader(pdfInputFileName);

    stp = PdfStamper.createSignature(reader, fout, '\0');
    PdfSignatureAppearance sap = stp.getSignatureAppearance();

    sap.setCrypto(privateKey, certificateChain, null, PdfSignatureAppearance.WINCER_SIGNED);

    sap.setReason(reason);
    sap.setLocation(location);
    sap.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
    sap.setVisibleSignature(new Rectangle(30, 830, 170, 770), 1, null);

    stp.close();

} catch (DocumentException | IOException e) {

    logger.error("An unknown error accoured while signing the PDF file: " + e.getMessage());
}

这是此代码签名的PDF的链接,当我打印它时,签名图章总是出现在打印件中: https://s3.amazonaws.com/gxzadminlocal/anexo_28276.pdf

1 个答案:

答案 0 :(得分:1)

如果签名字段尚不存在并且必须创建它,则当前的iText 5版本会自动设置PRINT标志。但是,如果您填写现有的签名字段,则该标志不会被更改。因此,您可能想在第一步中添加一个没有该PRINT标志的空签名字段,并在第二步中使用该字段进行签名,例如使用以下代码:

准备PDF

您可以准备一个具有空白签名字段的PDF,而无需设置PRINT标志,如下所示:

try (   InputStream resource = SOURCE_STREAM;
        OutputStream os = INTERMEDIATE_OUTPUT_STREAM) {
    PdfReader reader = new PdfReader(resource);
    PdfStamper stamper = new PdfStamper(reader, os);
    PdfFormField field = PdfFormField.createSignature(stamper.getWriter());
    field.setFieldName("Signature");
    field.setWidget(new Rectangle(30, 830, 170, 770), PdfAnnotation.HIGHLIGHT_NONE);
    stamper.addAnnotation(field, 1);
    stamper.close();
}

CreateSignature测试signWidgetNoPrint通过1)

尤其是你不

field.setFlags(PdfAnnotation.FLAGS_PRINT);

在这里!

签署准备好的PDF

已经创建了中间PDF,您可以像这样签名:

try (   InputStream resource = INTERMEDIATE_INPUT_STREAM;
        OutputStream os = RESULT_STREAM) {
    PdfReader reader = new PdfReader(resource);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');

    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setReason("reason");
    appearance.setLocation("location");
    appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
    appearance.setVisibleSignature("Signature");

    ExternalSignature pks = new PrivateKeySignature(pk, "SHA512", "BC");
    ExternalDigest digest = new BouncyCastleDigest();
    MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}

CreateSignature测试signWidgetNoPrint通过2)

假设您已经在pk中准备了私钥,并在chain中准备了证书链;并假设您已将Bouncy Castle注册为安全提供程序。

在结果PDF中,签名可视化出现在屏幕上,但不打印。