我尝试使用 itext 5.5.10 签署文档。我首先使用空签名对文件进行签名,然后从包含空签名的文件创建 SHA1 哈希。我调用我的 TSA 的 Web 服务来获取签名数据。
第一部分空签名
public void emptySignature(String src, String dest, String fieldname) 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(0,0,0,0), 1, fieldname);
ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ETSI_RFC3161);
MakeSignature.signExternalContainer(appearance, external, 8192);
}
第二部分哈希pdf
public byte[] getPdfHash(@NotNull Calendar signDate, int estimatedSize, @NotNull String hashAlgorithm,
boolean isTimestampOnly) throws Exception {
pdfReader = new PdfReader(inputFilePath, pdfPassword != null ? pdfPassword.getBytes() : null);
AcroFields acroFields = pdfReader.getAcroFields();
boolean hasSignature = acroFields.getSignatureNames().size() > 0;
byteArrayOutputStream = new ByteArrayOutputStream();
pdfStamper = PdfStamper.createSignature(pdfReader, byteArrayOutputStream, '\0', null, hasSignature);
pdfStamper.setXmpMetadata(pdfReader.getMetadata());
pdfSignatureAppearance = pdfStamper.getSignatureAppearance();
pdfSignature = new PdfSignature(PdfName.ADOBE_PPKLITE,
isTimestampOnly ? PdfName.ETSI_RFC3161 : PdfName.ADBE_PKCS7_DETACHED);
pdfSignature.setReason(signReason);
pdfSignature.setLocation(signLocation);
pdfSignature.setContact(signContact);
pdfSignature.setDate(new PdfDate(signDate));
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(certificationLevel);
}
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, new Integer(estimatedSize * 2 + 2));
pdfSignatureAppearance.preClose(exc);
MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm);
InputStream rangeStream = pdfSignatureAppearance.getRangeStream();
int i;
while ((i = rangeStream.read()) != -1) {
messageDigest.update((byte) i);
}
return messageDigest.digest();
}
第三部分签名
public void signExternalContainer( byte[] externalSignature, int estimatedSize) throws GeneralSecurityException, IOException, DocumentException {
InputStream data = pdfSignatureAppearance.getRangeStream();
byte[] encodedSig =externalSignature;
if (estimatedSize < encodedSig.length)
throw new IOException("Not enough space");
byte[] paddedSig = new byte[estimatedSize];
Arrays.fill(paddedSig, (byte) 32);
System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);
PdfDictionary dic2 = new PdfDictionary();
dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(false));
pdfSignatureAppearance.close(dic2);
}
我得到这个错误
Exception in thread "main" java.lang.IllegalArgumentException: The key /Contents is too big. Is 8272, reserved 2
at com.itextpdf.text.pdf.PdfSignatureAppearance.close(PdfSignatureAppearance.java:1476)
我试图修复错误但没有成功。我希望你帮我找到解决办法。我以 itext 的基本示例为基础。预先感谢您的帮助。