我有这种情况.
我有一个生成PDF的应用程序,需要签名.
我们没有签署文档的证书,因为它们在HSM中,我们使用证书的唯一方法是使用Web服务.
此Web服务提供两个选项,发送PDF文档,并返回已签名的pdf,或发送将要签名的哈希.
第一个选项是不可行的,因为PDF没有时间戳签名(这是一个非常重要的必要条件),因此选择了第二个选项.
这是我们的代码,首先,我们得到签名外观,并计算哈希:
PdfReader reader = new PdfReader(Base64.decode(pdfB64));
reader.setAppendable(true);
baos = new ByteArrayOutputStream();
PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0', null, true);
appearance = stamper.getSignatureAppearance();
appearance.setCrypto(null, chain, null, PdfSignatureAppearance.SELF_SIGNED);
appearance.setVisibleSignature("Representant");
cal = Calendar.getInstance();
PdfDictionary dic = new PdfDictionary();
dic.put(PdfName.TYPE, PdfName.SIG);
dic.put(PdfName.FILTER, PdfName.ADOBE_PPKLITE);
dic.put(PdfName.SUBFILTER, new PdfName("adbe.pkcs7.detached"));
dic.put(PdfName.M, new PdfDate(cal));
appearance.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, Integer.valueOf(reservedSpace.intValue() * 2 + 2));
appearance.setCertificationLevel(1);
appearance.preClose(exc);
AbstractChecksum checksum = JacksumAPI.getChecksumInstance("sha1");
checksum.reset();
checksum.update(Utils.streamToByteArray(appearance.getRangeStream()));
hash = checksum.getByteArray();
Run Code Online (Sandbox Code Playgroud)
在这一点上,我们有文档的哈希码.然后我们将哈希发送到webservice,我们得到签名的哈希码.
最后,我们将签名的哈希值放到PDF中:
byte[] paddedSig = …Run Code Online (Sandbox Code Playgroud)