使用iText实现PDF延迟签名后签名验证失败求助
iText延迟签名验证失败排查与证书链使用疑问
我在使用iText实现PDF延迟签名时,遇到签名验证失败的问题,系统提示“文档在签名后已被更改或损坏”。参考相关问题修改代码后,问题仍未解决。同时我有一个疑问:延迟签名前无法获取Certificate链,该如何使用emptySignature方法的chain参数?
核心实现代码
public static void emptySignature(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(50, 780, 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")); // 需要将此哈希值传给第三方系统,获取签名后的哈希用于验证 System.out.println("Hash: " + Base64.getEncoder().encodeToString(hash)); } public static void createSignature(String src, String dest, String fieldname, PrivateKey pk, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException { PdfReader reader = new PdfReader(src); FileOutputStream os = new FileOutputStream(dest); ExternalSignatureContainer external = new MyExternalSignatureContainer(pk, chain); MakeSignature.signDeferred(reader, fieldname, os, external); }
main方法代码
public static void main(String[] args) throws DocumentException, GeneralSecurityException, IOException { // 1. 生成临时空签名文件 emptySignature("mypdf.pdf", "temp.pdf", "", null);// 延迟签名前无法获取chain?该如何使用这个参数? // 2. 从第三方系统获取证书 Certificate[] cert = getCert(); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(new FileInputStream("aaa.p12"), "ogcio".toCharArray()); String alias = ks.aliases().nextElement(); PrivateKey pk = (PrivateKey) ks.getKey(alias, "ogcio".toCharArray()); createSignature("temp.pdf", "result.pdf", "", pk, cert); }
MyExternalSignatureContainer类代码
public class MyExternalSignatureContainer implements ExternalSignatureContainer { protected PrivateKey pk; protected Certificate[] chain; public MyExternalSignatureContainer(PrivateKey pk, Certificate[] chain) { this.pk = pk; this.chain = chain; } public byte[] sign(InputStream is) throws GeneralSecurityException { try { Security.addProvider(new BouncyCastleProvider()); PrivateKeySignature signature = new PrivateKeySignature(pk, "SHA256", "BC"); String hashAlgorithm = signature.getHashAlgorithm(); BouncyCastleDigest digest = new BouncyCastleDigest(); PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false); byte[] hash = DigestAlgorithms.digest(is, digest.getMessageDigest(hashAlgorithm)); byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, MakeSignature.CryptoStandard.CMS); byte[] extSignature = signature.sign(sh); sgn.setExternalDigest(extSignature, null, signature.getEncryptionAlgorithm()); return sgn.getEncodedPKCS7(hash, null, null, null, MakeSignature.CryptoStandard.CMS); } catch (IOException ioe) { throw new ExceptionConverter(ioe); } } public void modifySigningDictionary(PdfDictionary signDic) { //signDic.put(PdfName.FILTER, PdfName.ADOBE_PPKLITE); //signDic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_DETACHED); } }
我已上传问题PDF文件,恳请帮忙排查签名验证失败的原因。
内容的提问来源于stack exchange,提问作者NeeDKK
相关产品推荐
相关产品推荐

