I'm sign document, using Itext. I have that method:
public static void sign(String src, String dest, Certificate[] chain,PrivateKey pk, String digestAlgorithm, String provider,CryptoStandard subfilter, TSAClient tsa )
{
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(new Rectangle(10, 20, 100, 200), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk,
digestAlgorithm, provider);
MakeSignature.signDetached(appearance, digest, signature, chain, null,null, tsa, 0, subfilter);
// ALREADY SIGNED. ADD LTB NOW.
CrlClient crlClient = new CrlClientOnline("http://crl.mycrl.com/mycrl.crl");
OcspClient ocspClient=new OcspClientBouncyCastle();
addLtv(DEST, DEST2, ocspClient, crlClient, tsa);
}
and I sign:
sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "For Testing", " location", tsa);
everything works. PDF is signed well.
but then, I can't add ltv. I use code from itext documentation:
public static void addLtv(String src, String dest, OcspClient ocsp, CrlClient crl,
TSAClient tsa) throws IOException, DocumentException,
GeneralSecurityException {
PdfReader r = new PdfReader(src);
FileOutputStream fos = new FileOutputStream(dest);
PdfStamper stp = PdfStamper.createSignature(r, fos, '\0', null, true);
LtvVerification v = stp.getLtvVerification();
AcroFields fields = stp.getAcroFields();
List<String> names = fields.getSignatureNames();
String sigName = names.get(names.size() - 1);
PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
if (pkcs7.isTsp()) {
v.addVerification(sigName, ocsp, crl,
LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
else {
for (String name : names) {
v.addVerification(name, ocsp, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
}
PdfSignatureAppearance sap = stp.getSignatureAppearance();
LtvTimestamp.timestamp(sap, tsa, null);
}
EDITED: everything works, but at line LtvTimestamp.timestamp(sap, tsa, null); I have that error: Exception in thread "main" java.io.IOException: Not enough space
that's my pdf: https://www.dropbox.com/s/o05rw6ubiuslm4j/DOC_SIGNED.pdf
Exception in thread "main" java.io.IOException: Not enough space
at com.itextpdf.text.pdf.security.LtvTimestamp.timestamp(LtvTimestamp.java:103)
at ge.digital.signature.DocumentSigner.DigitalSignature.addLtv(MySignature.java:132)
at ge.digital.signature.DocumentSigner.DigitalSignature.main(MySignature.java:163)
That IOException
occurs when the space reserved in the PDF for the integration of the time stamp does not suffice. Thus, you have to change the method getTokenSizeEstimate
of the TSAClient
instance tsa
you call your sign
method with to return a larger estimate of the time stamp size.
In case of the TSAClientBouncyCastle
implementation of TSAClient
, e.g., you can make it return arbitrary estimates instead of the default 4096
if you use the constructor with four arguments:
public TSAClientBouncyCastle(String url, String username, String password, int tokSzEstimate)
Some background: When integrating a signature or a document time stamp into a PDF, you first prepare the PDF with a gap of a given size, then calculate the hash of everything but that gap, then sign or time stamp that hash, and finally integrate the generated signature or time stamp into that gap, e.g.
(That /ByteRange entry is part of the signed content. Thus, one cannot enlarge the gap afterwards.)
Therefore, you have to use some estimate of the size of the generated signature or time stamp before its generation.
In case of document time stamps, this estimate is provided by the TSAClient
method getTokenSizeEstimate.
PS: For still more details cf. this answer, the Adobe document Digital Signatures in a PDF (from which I copied the figure above), and the PDF specification ISO 32000-1:2008 made available here by Adobe.