java - 将签名的哈希嵌入到 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);
任何帮助,将不胜感激。
解决方案
推荐阅读
- c++ - Arduino/C++ 正确使用指针的方法
- c++ - 插入时同时遍历地图,以何种方式不安全
- javascript - 给每个元素一个不同的文本(循环,数组)
- objective-c - 目标 C 字典不返回相同的数字
- python - 使用 PyInstaller 可执行程序卡在循环中的进程
- linux - 作者如何知道具有 %100 certanity 的环境变量的地址?
- python - 多个用户的数据与单个 Twitter API 请求
- webview - 如何在屏幕更改时处理 Flutter WebviewScaffold?
- c# - ASP.NET Core 2.1 角色管理器注册
- python - 有没有办法从 DataFrame.from_dict 中删除列号和行号?