使用PKI SIM使用外部签名的iText签名PDF

时间:2019-12-27 08:24:51

标签: java pdf encryption itext sign

我正在尝试使用移动签名服务提供商(MSSP)对pdf文件进行签名。

我用下面的一些代码来做。但是签名无效,并显示消息“自应用签名以来,文档已被更改或损坏。”

在“ APWebService.sign(phoneNumber,messageDisplay,encode)”中进行编码只能接受44个字符。

有人可以帮助我吗?

public class MyExternalSignatureContainer implements ExternalSignatureContainer {

    protected byte[] sig;
    protected Certificate[] chain;

    public static final String SRC = "/media/thanhpx1/MEDIA/FileCongVan.pdf";
    public static final String TEMP = "/media/thanhpx1/MEDIA/hello_changed.pdf";
    public static final String DEST_SIGN = "/media/thanhpx1/MEDIA/signed.pdf";

    public MyExternalSignatureContainer(byte[] sig, Certificate[] chain) {
        this.sig = sig;
        this.chain = chain;
    }

    public MyExternalSignatureContainer(Certificate[] chain) {
        this.chain = chain;
    }

    public byte[] sign(InputStream is) throws GeneralSecurityException {
        return sig;
    }

    public byte[] emptySignature_hash(String src, String dest, String fieldname, Certificate[] chain)
            throws IOException, DocumentException, GeneralSecurityException, java.io.IOException {
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, fieldname);
        appearance.setCertificate(chain[0]);
        ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        MakeSignature.signExternalContainer(appearance, external, 8192);

        InputStream inp = appearance.getRangeStream();

        BouncyCastleDigest digest = new BouncyCastleDigest();

        byte[] hash = DigestAlgorithms.digest(inp, digest.getMessageDigest("SHA256"));
        return hash;
    }

    public byte[] signed_hash(byte[] hash, Certificate[] chain) throws GeneralSecurityException, MalformedURLException, java.io.IOException {
        BouncyCastleDigest digest = new BouncyCastleDigest();
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, digest, false);
        //hash.length=32
        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);       
        //sh.length=77
        InputStream shInputStream = new ByteArrayInputStream(sh);
        byte[] signedAttributesHash = DigestAlgorithms.digest(shInputStream, digest.getMessageDigest("SHA256"));
        //signedAttributesHash.length=32
        String encode = com.itextpdf.io.codec.Base64.encodeBytes(signedAttributesHash);
        //encode have 44 characters
        String phoneNumber = "xxxxxxxxx";
        String messageDisplay = "Please sign this document";

        //Send to Application Provider WS
        String resultSign = APWebService.sign(phoneNumber, messageDisplay, encode);
        //resultSign = W5srXKNmRdXNd7uX/QsYhBPet8DOdO9A6F/Ku5ey5JoTatYEJVaEvXB7MjZ3w2W2tEetpZVfc0eFSmMwp/z3TZVX7JvjiN0uCjXgFtCCRr7ffm+jcbp2MEK4hJCCNoHawpjvVV1Qykcg1gerHQDaSSQhtrfJsxOVd0KUIgfIJeBmGMZMGerdz+snH9pe74fMlX+IuEp5Hhk0R6xuwL9vKFxvCVPyv/U6eRmlQmG/wIzr6IBIWET0JDNNgWjmq+jKL70hxZLakZU9Hqu1zKzpkS5jB+0UXMayjBldBuPF1rofgRJKsT8BJttQ8a/YYZr6Sw0X8m8Ah+yPCGTWunRUhA==

        byte[] signedHashValue = com.itextpdf.io.codec.Base64.decode(resultSign);
        sgn.setExternalDigest(signedHashValue, null, "RSA");
        return sgn.getEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);

    }

    public void createSignature(String src, String dest, String fieldname, byte[] hash,
            Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException, java.io.IOException {

        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        ExternalSignatureContainer external = new MyExternalSignatureContainer(hash, chain);
        MakeSignature.signDeferred(reader, fieldname, os, external);
    }

    public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException, java.io.IOException {

        String phoneNumber = "xxxxxxxx";

        //Call from Application Provider WS to get certificate
        GetCertDto certDto = APWebService.getCertInfo(phoneNumber);     
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        ByteArrayInputStream bytes = new ByteArrayInputStream(Base64.decodeBase64(certDto.getValue()));
        X509Certificate cert = (X509Certificate)certFactory.generateCertificate(bytes);     
        X509Certificate[] certArr = new X509Certificate[1];
        certArr[0] = cert;

        MyExternalSignatureContainer app = new MyExternalSignatureContainer(certArr);
        byte[] hh = app.emptySignature_hash(SRC, TEMP, "sig1", certArr);
        byte[] hh_sign = (app.signed_hash(hh, certArr));
        app.createSignature(TEMP, DEST_SIGN, "sig1", hh_sign, certArr);
        System.out.println("done");
    }

    @Override
    public void modifySigningDictionary(PdfDictionary signDic) {

    }
}

0 个答案:

没有答案