首页 > 解决方案 > 将签名的哈希嵌入到 pdf - 文档自签名后已被更改或损坏

问题描述

我在stackoverflow中浏览过类似的帖子,但仍然没有运气!

我正在为 pdf 文件生成哈希值,将其发送到签名服务器,然后取回返回的签名哈希,并尝试将其附加到原始 pdf。

在 adobe reader 中验证签名 pdf 的签名时,我收到警告“文档自签名以来已被更改或损坏”。其他一切(签名者的身份、时间戳、证书)看起来都不错。

这就是我正在做的(签名的哈希存储在hashedSignature

PdfReader reader = new PdfReader(src);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');

Rectangle rect = new Rectangle(400, 20, 200, 80);   
        
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(rect, 1, signatureFieldName);
appearance.setCertificate(chain[0]);     
  
try
{
    appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
    appearance.setSignatureGraphic(Image.getInstance("[path to image file]");
}
catch (Exception e)
{ 
    appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
}
        
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.setReason(appearance.getReason());
dic.setLocation(appearance.getLocation());
dic.setContact(appearance.getContact());
dic.setDate(new PdfDate(appearance.getSignDate()));
appearance.setCryptoDictionary(dic);
      
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, Integer.valueOf(8192 * 2 + 2));
appearance.preClose(exc);
        
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);

OCSPVerifier ocspVerifier = new OCSPVerifier(null, null);
OcspClient ocspClient = new OcspClientBouncyCastle(ocspVerifier);
byte[] ocsp = null;
if (chain.length >= 2 && ocspClient != null) 
{
     ocsp = ocspClient.getEncoded((X509Certificate) chain[0], (X509Certificate) chain[1], null);
}

ByteArrayOutputStream os = baos;
byte[] signedHash = org.apache.commons.codec.binary.Base64.decodeBase64(hashedSignature.getBytes());

       
sgn.setExternalDigest(signedHash, null, "RSA");
Collection<byte[]> crlBytes = null;
TSAClientBouncyCastle tsaClient = new 
TSAClientBouncyCastle("http://timestamp.gdca.com.cn/tsa", null, null);

byte[] encodedSig = sgn.getEncodedPKCS7(signedHash, tsaClient, ocsp, crlBytes, MakeSignature.CryptoStandard.CMS);
byte[] paddedSig = new byte[8192];
System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);
PdfDictionary dic2 = new PdfDictionary();
dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));

try 
{
    appearance.close(dic2);
} 
catch (DocumentException e) 
{
    throw new IOException(e);
}

FileOutputStream fos = new FileOutputStream(new File(dest));
os.writeTo(fos);

任何帮助,将不胜感激。

标签: javapdfitextsigndigital

解决方案


推荐阅读