使用ITEXT 2.1.7或数字签名服务从PDF获得哈希



我正在将一个项目从itext 5迁移到itext 2/或dss(https://ec.europa.eu/cefdigital/wiki/wiki/wiki/display/cefdigital/esignature/esignature.plocy.plocy.ploes-phist.plo.clo.play/cefdigital一下P>

由于Itext版本之间的差异(DSS使用ITEXT 2.17(,我无法获得适当的签名哈希。

这里的代码从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,
                                                                '',
                                                                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的内容错误。

有人设法这样做吗?任何帮助将不胜感激。

pdfbox的特殊方法。

我不知道如何在空签名中插入公共证书:/like as itext!我不知道是否可能。

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();
}
}

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

最新更新