使用iText 2.1.7或Digital Signature Service从pdf获取哈希 [英] get hash from pdf with iText 2.1.7 or Digital Signature Service

查看:322
本文介绍了使用iText 2.1.7或Digital Signature Service从pdf获取哈希的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将项目从iText 5迁移到iText 2/或DSS( https://ec.europa.eu/cefdigital/wiki/display/CEFDIGITAL/eSignature .)

I'm migrating a project from iText 5 to iText 2/or DSS (https://ec.europa.eu/cefdigital/wiki/display/CEFDIGITAL/eSignature.)

由于iText版本之间的差异(DSS使用iText 2.17),我无法获得正确的带符号哈希.

Due to the difference between iText versions (DSS use iText 2.17) i can't get a proper signed hash.

此处是从itex 5迁移的代码:

Here the code migrated from itex 5 :

            // We get the self-signed certificate from the client
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            Certificate[] chain = new Certificate[1];
            chain[0] = factory.generateCertificate(new ByteArrayInputStream(decoded));

            // we create a reader and a stamper
            PdfReader reader = new PdfReader(hash.getInputFile());
            try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

                PdfStamper stamper = PdfStamper.createSignature(reader,
                                                                byteArrayOutputStream,
                                                                '\0',
                                                                null,
                                                                true);

                // HERE WE HAD SOME DIFFERENCE                 
                PdfSignatureAppearance sap = stamper.getSignatureAppearance();

                sap.setVisibleSignature(new Rectangle(36, 748, 36, 748), 1, signField); //invisible

                // iText 5: 
                //sap.setCertificate(chain[0]);

                // iText 2.1.7: 
                sap.setCrypto(null,chain,null,PdfSignatureAppearance.SELF_SIGNED);


                PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
                dic.setReason(sap.getReason());
                dic.setLocation(sap.getLocation());
                dic.setContact(sap.getContact());

                dic.setDate(new PdfDate(sap.getSignDate()));
                sap.setCryptoDictionary(dic);
                HashMap<PdfName,Integer> exc = new HashMap<>();
                exc.put(PdfName.CONTENTS, 8192 * 2 + 2);
                sap.preClose(exc);



                // iText 5: 
                /* 
                ExternalDigest externalDigest = hashAlgorithm ->
                        DigestAlgorithms.getMessageDigest(hashAlgorithm, null);

                ExternalDigest externalDigest = new ExternalDigest() {
                    public MessageDigest getMessageDigest(String hashAlgorithm)
                            throws GeneralSecurityException {
                        return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
                    }
                };

                PdfPKCS7 sgn = new PdfPKCS7(null,
                        chain,
                        "SHA256",
                        null,
                        externalDigest,
                        false);
                */
                // iText 2.1.7: 
                PdfPKCS7 sgn = new PdfPKCS7(null,chain,null, "SHA256",null,false);

                // WARNING SAP.getRange different response content!!!
                InputStream data = sap.getRangeStream();


                // iText 5:
                //byte[] hashArray = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));

                //iText 2
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                byte[] hashArray = md.digest(IOUtils.toByteArray(data));


                byte[] ocsp = null;

                // iText 5:
                //byte[] sh = sgn.getAuthenticatedAttributeBytes(hashArray,
                //      null,
                //      null,
                //      MakeSignature.CryptoStandard.CMS);

                // iText 2:
                Calendar cal = Calendar.getInstance();
                byte[] sh = sgn.getAuthenticatedAttributeBytes(hashArray,cal,null);

                InputStream shInputStream = new ByteArrayInputStream(sh);

                // iText 5:
                //byte[] signedAttributesHash = DigestAlgorithms.digest(shInputStream,externalDigest.getMessageDigest("SHA256"));

                // iText 2:
                byte[] signedAttributesHash = md.digest(IOUtils.toByteArray(shInputStream));                


                hash.setOcsp(ocsp);                
                hash.setSgn(sgn);
                hash.setFilehash(hashArray);
                hash.setSap(sap);
                hash.setBaos(byteArrayOutputStream);

                hash.setSignedAttributesHashB64(new String(
                    org.bouncycastle.util.encoders.Base64.encode(signedAttributesHash),
                    Charsets.UTF_8)
                );

问题始于sap.getRangeStream();,输出不同. 以下变量shsignedAttributesHash的内容错误.

The problems starts around sap.getRangeStream();, the output are different. The following variables sh and signedAttributesHash had wrong content.

有人成功做到了吗?任何帮助将不胜感激.

Did someone manage to do this? Any help would be much appreciated.

推荐答案

带有pdfbox的临时方法.

Temorary approach with pdfbox.

我不知道如何将公共证书插入空签名中:/就像iText一样!我不知道是否可能.

I can't figure out how to insert the public certificate inside the empty signature :/ like as iText ! I don't know if is possible.

public abstract class testtwostep
{

private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
private static final String ID_MD5 = "1.2.840.113549.2.5";
private static final String ID_MD2 = "1.2.840.113549.2.2";
private static final String ID_SHA1 = "1.3.14.3.2.26";
private static final String ID_RSA = "1.2.840.113549.1.1.1";
private static final String ID_DSA = "1.2.840.10040.4.1";
private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3";
private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";
private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5";
private static final String ID_MD2RSA = "1.2.840.113549.1.1.2";
private static final String ID_MD5RSA = "1.2.840.113549.1.1.4";
private static final String ID_SHA1RSA = "1.2.840.113549.1.1.5";


public byte[] getAuthenticatedAttributeBytes(byte secondDigest[],Calendar signingTime) throws IOException {

    ASN1EncodableVector attribute = new ASN1EncodableVector();
    ASN1EncodableVector v = new ASN1EncodableVector();
    v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
    v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
    attribute.add(new DERSequence(v));
    v = new ASN1EncodableVector();
    v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
    v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
    attribute.add(new DERSequence(v));
    v = new ASN1EncodableVector();
    v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
    v.add(new DERSet(new DEROctetString(secondDigest)));
    attribute.add(new DERSequence(v));
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    ASN1OutputStream dout = new ASN1OutputStream(bOut);
    dout.writeObject(new DERSet(attribute));
    dout.close();
    return bOut.toByteArray();
}

public byte[] getHash() throws IOException, NoSuchAlgorithmException, CertificateException {
    String documentFile = "/home/gigio2k/dev/swap/tmp.pdf";
    String documentFileSigned = "/home/gigio2k/dev/swap/tmp_pdfbox.pdf";
    String certStr = "MII....GsNw==";
    byte[] certByte = org.apache.commons.codec.binary.Base64.decodeBase64(certStr.getBytes());

    PDDocument document = PDDocument.load(new File(documentFile));

    Calendar date = Calendar.getInstance();
    long SeedTS = date.getTimeInMillis();
    document.setDocumentId(SeedTS);


    PDSignature signature = new PDSignature();
    signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
    signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
    //signature.setName("Example User");
    signature.setLocation("Los Angeles, CA");
    signature.setReason("Testing");
    signature.setSignDate(date);


    SignatureOptions opt = new SignatureOptions();
    opt.setPreferredSignatureSize(8192);

    document.addSignature(signature,opt);

    ExternalSigningSupport externalSigningSupport = document.saveIncrementalForExternalSigning(null);

    byte[] content = IOUtils.toByteArray(externalSigningSupport.getContent());
    MessageDigest md = MessageDigest.getInstance("SHA256", new BouncyCastleProvider());
    byte[] digest = md.digest(content); // this is sent to client


   //byte[] sh = sgn.getAuthenticatedAttributeBytes(hashArray,null,null,MakeSignature.CryptoStandard.CMS);

        byte[] sh = getAuthenticatedAttributeBytes(digest,date);
        InputStream shInputStream = new ByteArrayInputStream(sh);
        //byte[] signedAttributesHash = DigestAlgorithms.digest(shInputStream, externalDigest.getMessageDigest("SHA256"));
        byte[] signedAttributesHash = md.digest(sh);



        System.out.println("--------------------");
        System.out.println(new String(org.bouncycastle.util.encoders.Base64.encode(signedAttributesHash),Charsets.UTF_8));
    System.out.println(date.getTimeInMillis());
    System.out.println("--------------------");
    System.out.println("Enter b64 signed:");
    System.out.println("--------------------");

    Scanner in = new Scanner(System.in);
    String signedHashB64 = in.nextLine();
    byte[] encodedSignature = org.apache.commons.codec.binary.Base64.decodeBase64(signedHashB64.getBytes());

    PDDocument document2 = PDDocument.load(new File(documentFile));

    Calendar date2 = date;
    document2.setDocumentId(SeedTS);

    PDSignature signature2 = new PDSignature();
    signature2.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
    signature2.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
    //signature2.setName("Example User");
    signature2.setLocation("Los Angeles, CA");
    signature2.setReason("Testing");
    signature2.setSignDate(date2);

    SignatureOptions opt2 = new SignatureOptions();
    opt2.setPreferredSignatureSize(8192);

    document2.addSignature(signature2,opt2);

    File file = new File(documentFileSigned);
    FileOutputStream fos = new FileOutputStream(file);
    ExternalSigningSupport externalSigning = document2.saveIncrementalForExternalSigning(fos);
    externalSigning.setSignature(encodedSignature);

    System.out.println("--------------------");
    System.out.println("saved to: " + documentFileSigned);
    System.out.println("--------------------");
    return digest;
}

public static void main(String[] args) throws IOException, GeneralSecurityException
{
    testtwostep t2s = new testtwostep();
    t2s.getHash();
}
}

请注意:我没有编辑第一个问题,因为我会尝试更多方法,最后我会编辑原始问题

Please note: i didn't edit the first question because i'll try more way, at the end i edit the original question

这篇关于使用iText 2.1.7或Digital Signature Service从pdf获取哈希的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆