使用iText7为已数字签名的PDF文档添加密码遇阻
解决iText 7.2.2给已签名PDF加密码且保留签名的问题
问题根源
PDF数字签名靠文档内容的哈希值验证有效性,用非追加模式修改文档时,iText会重写整个文档结构(比如交叉引用表),这会改变原文档字节,直接导致签名失效。而你之前在PdfWriter的WriterProperties里设置加密,在追加模式下只会对新追加的内容生效,不会更新整个文档的加密配置,所以最终输出的文档没密码保护。
可行方案
改用PdfDocument.setEncryption()方法在追加模式下设置加密,这个方法能在保留原有签名的前提下,更新整个文档的加密规则。另外如果待处理的已签名文档本身是加密状态,读取时得先解密:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream pdfStream = new ByteArrayInputStream(pdf); // 要是原已签名文档是加密的,得先设置密码解密才能读取 ReaderProperties readerProps = new ReaderProperties().setPassword(password.getBytes()); PdfReader reader = new PdfReader(pdfStream, readerProps); // 创建Writer时先不设置加密 PdfWriter writer = new PdfWriter(baos); // 用追加模式打开文档,保证原有签名不被破坏 PdfDocument pdfDoc = new PdfDocument(reader, writer, new StampingProperties().useAppendMode()); // 打开文档后再设置加密参数,覆盖原有加密配置 pdfDoc.setEncryption( password.getBytes(), password.getBytes(), EncryptionConstants.ALLOW_PRINTING, EncryptionConstants.ENCRYPTION_AES_256 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA ); pdfDoc.close();
要点说明
- 追加模式的作用:完全保留原文档的所有内容和签名信息,只在文档末尾追加新的加密配置和交叉引用表,不会改动原签名依赖的哈希值,所以签名依然有效。
- setEncryption的优势:在追加模式下调用这个方法,会把加密规则应用到整个文档(包括原有内容和新追加部分),打开时必须输入密码验证。
- 加密文档读取:如果要处理的已签名文档本身是加密状态,一定要在
PdfReader里设置密码解密,不然根本读不了文档。
内容的提问来源于stack exchange,提问作者Cemail Sn
相关产品推荐
相关产品推荐

