当前位置: 首页 > 知识库问答 >
问题:

使用iText 2.1.7或数字签名服务从pdf中获取哈希

隆飞宇
2023-03-14
            // 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的内容错误。

有人设法做到了吗?任何帮助都将不胜感激。

共有1个答案

淳于星宇
2023-03-14

使用PDFBOX的临时方法。

我想不通如何将公共证书插入空签名:/like中作为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();
}
}

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

 类似资料:
  • 我正在尝试用DSS签署PDF文档,我的问题是我无法在服务器a中计算文档的哈希值,然后在服务器B中签署它。 知道服务器A包含PDF文档,我们在服务器B中检索用于签名的证书 我的问题是如何在不需要证书的情况下计算服务器a中文档的哈希值。然后在服务器B上发送签名? 更新: ******散列的准备和计算******** ******散列签名******** ********PDF错误:*********

  • 问题内容: 我正在编写一个Java网络服务,该网络服务从网络中的某些客户端使用iText对PDF文档进行签名。文档已正确签名,可以使用外部工具进行验证。但是,由于某些法律限制,为了将此文档存储在正式的文档库中,我必须提供签名中的哈希/摘要消息。 我已经尝试了几乎所有方法来获取该哈希,但是我可以获取的最接近的方法是使用此代码段将整个签名(CERT + HASH / DIGEST + TIMESTAM

  • 我正在编写一个Java web服务,它使用来自网络中一些客户端的iText对PDF文档进行签名。文档的签名正确,可以使用外部工具进行验证。然而,由于一些法律限制,为了将此文档存储在一个正式的文档存储库中,我必须提供来自签名的散列/摘要消息。 我已经尝试了几乎所有的方法来获得那个散列,但我能得到的最接近的方法是用下面的代码段以字符串的形式获得整个签名(证书+散列/摘要+时间戳)(请原谅字符串和[1]

  • 是否可以用开放源码软件库pdfbox提取已签名PDF的可见签名(图像)? 工作流: null 像下面这样的oop风格的东西会很棒: 找到了类PDSignature和如何签署一个PDF,但没有解决方案提取一个可见的签名作为图像。

  • 我有一个场景,我需要用iText7库从pdf中获取签名信息。签名可能存在,也可能不存在。当我为没有任何数字签名的PDF实例化一个新的对象时,会出现异常 “没有相关的PdfWriter用于进行间接操作。” .如果有签名,就很好用。我不确定如何纠正这个异常。 更新为包含代码示例

  • 我有一个应用程序生成一个PDF,需要签名。 我们没有用于签署文档的证书,因为它们在HSM中,而我们可以使用证书的唯一方法是使用WebService。 这是我们的代码,首先,我们得到签名外观,并计算散列 在这一点上,我们得到一个已签名的PDF,但签名无效。Adobe称“文档自签署以来已被更改或损坏”。 我已经通过使用外部服务和iText,PDF签名iText pkcs7多签名和是否可能签署一个PDF