For those who like to use timestamping (without OCSP, I haven't figured that 
one out yet), are frustrated about the lack of examples, and who don't want to 
spend a day digging in code and specifications, here's some sample code.

The following code was tested with Sun Java 1.6.0_07, with a third party source 
PDF (apparently generated by Neevia docuPrinter Pro v5.2), and verified in 
Adobe Acrobat 7.0.8
The sample requires iText 2.1.6 and BouncyCastle (I used v1.4.1).

Tested with (free) TSAs:
- https://tsa.aloaha.com/tsa.asp
- http://dse200.ncipher.com/TSS/HttpTspServer

-----8<-----8<-----8<-----8<-----8<-----
static void signAndTimestamp(final InputStream originalPdf, final OutputStream 
targetPdf, final PrivateKey pk, final X509Certificate[] certChain, final CRL[] 
revoked, final String tsaAddress) throws IOException, DocumentException, 
NoSuchAlgorithmException, InvalidKeyException, SignatureException
{
  // only an estimate, depends on the certificates returned by the TSA
  final int timestampSize = 4400;
  Security.addProvider(new BouncyCastleProvider());

  final PdfReader reader = new PdfReader(originalPdf);
  final PdfStamper stamper = PdfStamper.createSignature(reader, targetPdf, 
'\0');
  final PdfSignatureAppearance sap = stamper.getSignatureAppearance();

  // comment next lines to have an invisible signature
  sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
  sap.setLayer2Text("This is some custom made text.\n\nDate: some date");

  final PdfSigGenericPKCS sig = new PdfSigGenericPKCS.PPKMS("BC");
  final HashMap<PdfName, Integer> exclusionSizes = new HashMap<PdfName, 
Integer>();

  // some informational fields
  sig.setReason("Because I like iText's ability to sign PDFs");
  sig.setLocation("Multiverse command center");
  sig.setContact("[email protected]");
  sig.setName(PdfPKCS7.getSubjectFields(certChain[0]).getField("CN"));
  sig.setDate(new PdfDate(Calendar.getInstance()));

  // signing stuff
  final byte[] digest = new byte[256];
  final byte[] rsaData = new byte[20];
  sig.setExternalDigest(digest, rsaData, "RSA");
  sig.setSignInfo(pk, certChain, revoked);
  final PdfString contents = (PdfString)sig.get(PdfName.CONTENTS);
  // *2 to get hex size, +2 for delimiters
  PdfLiteral contentsLit = new PdfLiteral((contents.toString().length() + 
timestampSize) * 2 + 2);
  exclusionSizes.put(PdfName.CONTENTS, new Integer(contentsLit.getPosLength()));
  sig.put(PdfName.CONTENTS, contentsLit);

  // certification; will display dialog or blue bar in Acrobat Reader
  
sap.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);

  // process all the information set above
  sap.setCryptoDictionary(sig);
  sap.preClose(exclusionSizes);

  // calculate digest (hash)
  final MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
  final byte[] buf = new byte[8192];
  int n;
  final InputStream inp = sap.getRangeStream();
  while ((n = inp.read(buf)) != -1)
  {
    messageDigest.update(buf, 0, n);
  }
  final byte[] hash = messageDigest.digest();

  // make signature (SHA1 the hash, prepend algorithm ID, pad, and encrypt with 
RSA)
  final Signature sign = Signature.getInstance("SHA1withRSA");
  sign.initSign(pk);
  sign.update(hash);
  final byte[] signature = sign.sign();

  // prepare the location of the signature in the target PDF
  contentsLit = (PdfLiteral)sig.get(PdfName.CONTENTS);
  final byte[] outc = new byte[(contentsLit.getPosLength() - 2) / 2];
  final PdfPKCS7 pkcs7 = sig.getSigner();
  pkcs7.setExternalDigest(signature, hash, "RSA");
  final PdfDictionary dic = new PdfDictionary();

  // retrieve a timestamp and combine it with our signature into a single blob 
of data, formatted as PKCS7 signed message
  final byte[] ssig = pkcs7.getEncodedPKCS7(null, null, new 
TSAClientBouncyCastle(tsaAddress), null);
  System.arraycopy(ssig, 0, outc, 0, ssig.length);

  // add the timestamped signature
  dic.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));

  // finish up
  sap.close(dic);
}
-----8<-----8<-----8<-----8<-----8<-----

Regards,

Bert Vingerhoets - Research & Development
Inventive Designers NV

Phone: +32 3 821 01 70
Fax: +32 3 821 01 71
Email: Bert_Vingerhoets at inventivegroup dot com
http://www.inventivegroup.com/


-----Original Message-----
From: Paulo Soares [mailto:[email protected]]
Sent: Thursday 2 July 2009 13:32
To: Post all your questions about iText here
Subject: Re: [iText-questions] TSA in iText 2.1.6

TSA in iText is oriented to be used inside an external signature with signed 
attributes to also support OCSP. The main objective was to make it work, now 
we'll have to improve on the details.

Paulo

> -----Original Message-----
> From: Bert Vingerhoets [mailto:[email protected]]
> Sent: Thursday, July 02, 2009 12:01 PM
> To: [email protected]
> Subject: [iText-questions] TSA in iText 2.1.6
>
> Hi,
>
> I was checking out the new functionality of iText 2.1.6, especially
> the added TSA support.
>
> In absence of documentation or examples, I took a look at the code to
> determine how to use the timestamping functionality.
> However, all I could find about the subject were the interface
> TSAClient and class TSAClientBouncyCastle. Neither of which are
> instantiated anywhere, the only references of TSAClient I could find
> were in one PdfPKCS7#getEncodedPKCS7 method that isn't used by the
> rest of iText (except for filling the TSAClient argument with null).
>
> When following the examples for PDF signing using external signatures,
> one of the getEncodedPKCS7() methods does get called outside of iText
> (for setting the CONTENTS key in the dictionary passed to the final
> PdfSignatureAppearance#close() invocation). However, When I replace
> this getEncodedPKCS7() call by the overload that accepts a TSAClient,
> the resulting array is too large to fit in the allocated buffer.
> Checking where this buffer gets allocated leads to an internal
> invocation of getEncodedPKCS7() (without TSAClient argument).
>
> As far as I can see, being able to use TSA in iText requires me to
> patch the library (luckily we're using the MPL license) or try to
> externalize the entire contents of the 'if (cryptoDictionary ==
> null)'-branch from
> PdfSignatureAppearance#preClose() where the CONTENTS buffer is
> allocated with the first call (through
> sigStandard.setSignInfo) to getEncodedPKCS7.
> Patching iText to allow specifying a TSAClient externally seems the
> easiest option to me.
>
> Is this correct? Or is there another way to use TSA in iText?
>
>
> On a brighter note, once I hacked the library to effectively use a
> TSAClient, a correct PDF was indeed produced and recognized by Acrobat
> Reader; so the code does, in fact, work.
>
>
> Regards,
>
> Bert Vingerhoets - Research & Development Inventive Designers NV
>
> Phone: +32 3 821 01 70
> Fax: +32 3 821 01 71
> Email: Bert_Vingerhoets at inventivegroup dot com
> http://www.inventivegroup.com/
>
>
> Inventive Designers' Email Disclaimer:
> http://www.inventivedesigners.com/email-disclaimer


Aviso Legal: Esta mensagem ? destinada exclusivamente ao destinat?rio. Pode 
conter informa??o confidencial ou legalmente protegida. A incorrecta 
transmiss?o desta mensagem n?o significa a perca de confidencialidade. Se esta 
mensagem for recebida por engano, por favor envie-a de volta para o remetente e 
apague-a do seu sistema de imediato. ? proibido a qualquer pessoa que n?o o 
destinat?rio de usar, revelar ou distribuir qualquer parte desta mensagem.   
Disclaimer: This message is destined exclusively to the intended receiver. It 
may contain confidential or legally protected information. The incorrect 
transmission of this message does not mean the loss of its confidentiality. If 
this message is received by mistake, please send it back to the sender and 
delete it from your system immediately. It is forbidden to any person who is 
not the intended receiver to use, distribute or copy any part of this message.


--
This message has been scanned for viruses and dangerous content by MailScanner, 
and is believed to be clean.
--



Inventive Designers' Email Disclaimer:
http://www.inventivedesigners.com/email-disclaimer

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
--



------------------------------------------------------------------------------
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions

Buy the iText book: http://www.1t3xt.com/docs/book.php
Check the site with examples before you ask questions: 
http://www.1t3xt.info/examples/
You can also search the keywords list: http://1t3xt.info/tutorials/keywords/

Reply via email to