0

我尝试使用 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 的基本示例为基础。预先感谢您的帮助。

4

0 回答 0