使用iText旋转PdfSignatureAppearance

时间:2012-08-22 21:48:21

标签: java rotation itext electronic-signature

我在尝试在iText(例如90度)中旋转PdfSignatureAppearance时遇到了一个大问题。我正在使用MakeSignature.signDetached方法签署PDF,并为外观设置我自己的文本和图像。

以下是一些代码:

PdfReader reader = new PdfReader("my input file");
FileOutputStream fout = new FileOutputStream("my output file");

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

sap.setLayer2Text("Signed by someone");
sap.setAcro6Layers(true);
sap.setSignatureGraphic("my signature image", null));
sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION);

Rectangle pageSize = reader.getPageSize(1); //the page to sign: 1 is the 1st one

Rectangle rect = new Rectangle(llx, lly, urx, ury, rotation);
//llx, lly ... come from a GUI. They are working fine, but the rotation is not considered

sap.setVisibleSignature(rect, 1, null); //1 is the page to sign

MakeSignature.signDetached(sap, ...); //sign the document

我的问题是“轮换”参数。无论我设置什么,文字和图像都不会旋转。查看iText代码(我使用的是iText 5.3.2),签名图层边界框的旋转参数将被丢弃,因此,以这种方式设置旋转根本没有效果。

现在的问题是:有没有办法旋转我的签名图层而不重写整个PdfSignatureAppearance和MakeSignature类?

只是为了澄清:对文档进行数字签名的代码工作正常。我唯一的问题是签名的可视层:我无法旋转它。

感谢。

2 个答案:

答案 0 :(得分:1)

使用setRenderingMode(),setLayer2Text(),setSignatureGraphic()等便捷方法创建签名时,目前不支持设置旋转...

所以你有两个选择: 1.要么我们提供该功能。数字签名白皮书的前90页草案刚刚发布给新闻信的订阅者,所以我们正在研究这些课程。但是:使用智能卡进行签名,重构验证过程等......暂时具有绝对优先权,因此您可能需要等待一段时间。 2.使用getLayer()方法以任何方向绘制内容。对于背景中的图像,这将是getLayer(0);和getLayer(2)的文本。

请注意,曾经有过第1,3,4层,但它们只有在acro6Layers等于true时才有效;这是你的情况,但不鼓励使用acro6Layers(它已经过时了:你不应该再使用它了)。事实上,我现在就弃用该方法,默认情况下将该值设置为false。

答案 1 :(得分:1)

允许重用com.itextpdf.text.pdf.PdfSignatureAppearance中代码的工作示例(例如,自动计算字体大小):

public class RotateVisualSignature {
    public static void main(String[] args) throws IOException, DocumentException, GeneralSecurityException {
        // Loading private key and certificates.
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new FileInputStream("signer.p12"), "secret".toCharArray());
        String alias = keyStore.aliases().nextElement();
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, "secret".toCharArray());
        Certificate[] certificateChain = keyStore.getCertificateChain(alias);

        PdfReader reader = new PdfReader("sample.pdf");
        FileOutputStream os = new FileOutputStream("sample-signed.pdf");
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setCertificate(certificateChain[0]);

        // This method has to be called as an alternative to 'com.itextpdf.text.pdf.PdfSignatureAppearance.setVisibleSignature'.
        setVisibleSignatureRotated(stamper, appearance, new Rectangle(120, 650, 170, 770), 1, null);

        // Perform the signature.
        ExternalSignature externalSignature = new PrivateKeySignature(privateKey, "SHA-256", null);
        ExternalDigest externalDigest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, externalDigest, externalSignature, certificateChain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);
    }

    private static void setVisibleSignatureRotated(PdfStamper stamper, PdfSignatureAppearance appearance, Rectangle pageRect, int page, String fieldName) throws DocumentException, IOException {
        float height = pageRect.getHeight();
        float width = pageRect.getWidth();
        float llx = pageRect.getLeft();
        float lly = pageRect.getBottom();
        // Visual signature is configured as if it were going to be a regular horizontal visual signature.
        appearance.setVisibleSignature(new Rectangle(llx, lly, llx + height, lly + width), page, null);
        // We trigger premature appearance creation, so independent parts of it can be modified right away.
        appearance.getAppearance();
        // Now we correct the width and height.
        appearance.setVisibleSignature(new Rectangle(llx, lly, llx + width, lly + height), page, fieldName);
        appearance.getTopLayer().setWidth(width);
        appearance.getTopLayer().setHeight(height);
        PdfTemplate n2Layer = appearance.getLayer(2);
        n2Layer.setWidth(width);
        n2Layer.setHeight(height);
        // Then we rotate the n2 layer. See http://developers.itextpdf.com/question/how-rotate-paragraph.
        PdfTemplate t = PdfTemplate.createTemplate(stamper.getWriter(), height, width);
        ByteBuffer internalBuffer = t.getInternalBuffer();
        internalBuffer.write(n2Layer.toString().getBytes());
        n2Layer.reset();
        Image textImg = Image.getInstance(t);
        textImg.setInterpolation(true);
        textImg.scaleAbsolute(height, width);
        textImg.setRotationDegrees((float) 90);
        textImg.setAbsolutePosition(0, 0);
        n2Layer.addImage(textImg);
    }
}

结果如下:

rotated visual signature

要使用此功能,您只需按原样复制setVisibleSignatureRotated方法,并通过调用com.itextpdf.text.pdf.PdfSignatureAppearance#setVisibleSignature替换setVisibleSignatureRotated来电。