【问题标题】:Is it possible to sign a PDF document with hash and signed hash?是否可以使用哈希和签名哈希对 PDF 文档进行签名?
【发布时间】:2017-05-30 05:57:41
【问题描述】:

我可以使用带有外部签名的 itextpdf 库签署文档。

但问题是最终用户不想发送他的文档,因为它可能包含任何敏感数据。因此,我要求最终用户提供文档哈希以使用外部服务对哈希进行签名,并将签名的哈希发回。

但是,问题来了,当他们尝试使用 itextpdf (PdfSignatureAppearance) 使用给定的签名哈希对文档进行签名时,PDF 文档正在被签名。但是在验证签名时,它显示签名无效。

我在这里看到了同样的问题 Sign PDF using an external service and iText.

所以,问题的发生是因为每次我们使用PdfSignatureAppearance(itextpdf 库)打开文档时哈希都会失效。

谁能告诉我是否可以使用 itextpdf 库使用先前生成的散列和签名散列(我从外部服务获得)对 PDF 文档进行签名,以使散列不会失效?

【问题讨论】:

  • 我猜如果你直接使用 SHA512 之类的东西对 PDF 的字节进行散列,除非 PDF 内容发生变化,否则散列应该始终保持不变。
  • 对文档字节进行签名是不够的。某些属性也需要签名。您的最终客户不应在不使用 iText 的情况下创建散列。 @StoneBird 评论的另一个补充是您不能只散列完整的文档。您必须在要放置签名的 PDF 中留下一个“洞”。很明显,PDF 中的每个字节都应该被签名除了签名本身。
  • @Harish cf。 stack overflow documentation 了解 PDF 签名的一些背景。

标签: java pdf itext


【解决方案1】:
class MyExternalSignatureContainer implements ExternalSignatureContainer {
    protected byte[] sig;
    protected Certificate[] chain;
    protected PrivateKey pk;
    public MyExternalSignatureContainer(byte[] sig,Certificate[] chain,PrivateKey pk) {
        this.sig = sig;
        this.chain=chain;
        this.pk=pk;
    }
    public byte[] sign(InputStream is)throws GeneralSecurityException  {

        return sig;

    }
    public void modifySigningDictionary(PdfDictionary signDic) {
    }
}

 public byte[] emptySignature_hash(String src, String dest, String fieldname, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
        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, PrivateKey pk, Certificate[] chain)throws GeneralSecurityException{
        PrivateKeySignature signature = new PrivateKeySignature(pk, "SHA256", "SunPKCS11-eToken");

        //return extSignature;
       BouncyCastleDigest digest = new BouncyCastleDigest();
        Calendar cal = Calendar.getInstance();
        String hashAlgorithm = signature.getHashAlgorithm();
        System.out.println(hashAlgorithm);
        PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, digest, false);

        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
        byte[] extSignature = signature.sign(sh);

        System.out.println(signature.getEncryptionAlgorithm());

       // Calendar cal = Calendar.getInstance();
        sgn.setExternalDigest(extSignature, null, signature.getEncryptionAlgorithm());
    return sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);

        }
    public void createSignature(String src, String dest, String fieldname,byte[] hash, PrivateKey pk, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {

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


public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
 byte[] hh = app.emptySignature_hash(SRC, TEMP, "sig1", chain);
 byte[] hh_sign = (app.signed_hash(hh,  pk,  chain));

 app.createSignature(TEMP, DEST1, "sig1",hh_sign, pk, chain);

    }

【讨论】:

猜你喜欢
  • 2016-09-25
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2017-09-04
  • 2022-07-13
  • 1970-01-01
相关资源
最近更新 更多