我不明白为什么getRangeStream()返回的inputStream在同一文件的每次代码迭代中都不同。通常,它应该返回“使用外部签名时可哈希的文档字节”,对我来说,这意味着对于相同的输入文件,应返回相同的字节数组。但这不是...
PdfReader pdfReader = new PdfReader(new FileInputStream(inPdfFile), null);
AcroFields acroFields = pdfReader.getAcroFields();
boolean hasSignature = acroFields.getSignatureNames().size() > 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PdfStamper pdfStamper = PdfStamper.createSignature(pdfReader, byteArrayOutputStream, '\0', null, hasSignature);
pdfStamper.setXmpMetadata(pdfReader.getMetadata());
PdfSignatureAppearance pdfSignatureAppearance = pdfStamper.getSignatureAppearance();
PdfSignature pdfSignature = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
pdfSignature.setReason("reason");
pdfSignature.setLocation("location");
pdfSignature.setContact("contact");
pdfSignatureAppearance.setCryptoDictionary(pdfSignature);
// certify the pdf, if requested
/* if (certificationLevel > 0) {
// check: at most one certification per pdf is allowed
if (pdfReader.getCertificationLevel() != PdfSignatureAppearance.NOT_CERTIFIED)
throw new Exception("Could not apply -certlevel option. At most one certification per pdf is allowed, but source pdf contained already a certification.");
pdfSignatureAppearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
}*/
pdfSignatureAppearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, new Integer(30000 * 2 + 2));
pdfSignatureAppearance.preClose(exc);
InputStream rangeStream = pdfSignatureAppearance.getRangeStream();
答案 0 :(得分:1)
集成的pdf签名不是简单地按原样附加到现有pdf,而是签名表单字段(以及一些元信息)的值。互操作的此类签名必须在签名字段值中签名,但保留的空间除外。
因此,每当您尝试签署现有的pdf时,通常都必须准备它:如果pdf中还没有表单结构,则必须添加表单结构。如果还没有空的签名表单字段,则必须添加这样的表单字段。并且必须准备签名值,特别是签名时间。
无论何时创建或更新pdf,都会生成ID,确定创建或修改时间,并将这些数据添加到已创建/更新的pdf中。
因此,您的代码在每次运行中都会操纵源pdf,因此生成的pdf具有不同的ID,修改时间和签名时间。签名除了对占位符进行签名外,还对这些可变数据进行签名。
因此,每次运行的哈希值都不同。
有关更多详细信息,请阅读this answer和从那里引用的文章。