622 APPENDIX D Signing a PDF with a smart card In chapter 16, you learned how to add a digital signature to a PDF document using a (self-signed) certificate and a private key that is present somewhere on the file system. I also mentioned that this certificate and key are sometimes stored on a smart card. Figure D.1 shows an example of such a smart card. It’s a copy of my identity card. Figure D.1 A smart card containing my personal information Belgium is one of the first countries in the world to issue an electronic identity card (eID) as official proof of identity for its citizens. This identity card looks like a regular bankcard, with basic identity information in visual format, such as personal details and a photograph. It also contains a chip with the same information printed legibly on the card, the address of the card holder, and the identity and signature keys and certificates. The next example (written by Philippe Frankinet) uses this special card to add a digital signature to a PDF document. This example requires middleware that is specific for the type of smart card and smart card reader you’re using. It’s impossible to write a universal example that will work for every device and every type of card. The example is provided for your interest only; you’ll have to adapt it according to the requirements of your project: Certificate[] certs = new Certificate[1]; BelpicCard scd = new BelpicCard(""); certs[0] = scd.getNonRepudiationCertificate(); PdfReader reader = new PdfReader("unsigned.pdf"); B Signing a PDF with a smart card FileOutputStream fout = new FileOutputStream("signed.pdf"); PdfStamper stamper = PdfStamper.createSignature(reader, fout, '\0'); PdfSignatureAppearance sap = stamper.getSignatureAppearance(); sap.setCrypto( null, certs, null, PdfSignatureAppearance.SELF_SIGNED); sap.setReason("How to use iText a Belgian eID"); sap.setLocation("Belgium"); sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null); sap.setExternalDigest(new byte[128], new byte[20], "RSA"); sap.preClose(); PdfPKCS7 sig = sap.getSigStandard().getSigner(); byte[] content = streamToByteArray(sap.getRangeStream()); byte[] hash = MessageDigest.getInstance("SHA-1").digest(content); byte[] signatureBytes = scd.generateNonRepudiationSignature(hash); sig.setExternalDigest(signatureBytes, null, "RSA"); PdfDictionary dic = new PdfDictionary(); dic.put(PdfName.CONTENTS, new PdfString(sig.getEncodedPKCS1()).setHexWriting(true)); sap.close(dic); 623 C D E F G H This example is quite different from the examples you’ve seen elsewhere. In chapter 16, you learned how to retrieve the certificate and the private key from a keystore. Now you have to fetch the certificate from the smart card b. After you create a reader and a stamper object, you create a signature appearance. You don’t pass the private key with the method setCrypto() C. The private key is on the smart card, and there would be a serious security problem if you could read this private key. You have to sign the hash externally on the smart card reader D. To achieve this, you create a PdfPKCS7 instance E. PdfPKCS7 is a class that does all the processing related to signing. You create a hash of the document’s contents F and use middleware to sign it G. The signature appearance is stored as a PDF dictionary; sap.close() adds the CONTENTS entry to the signature H. This example uses the GoDot library. This library was written by Danny De Cock, and it can only be used with the Belgian eID. The object be.godot.sc.engine.BelpicCard retrieves the certificate b and signs the hash G. You’ll have to replace these lines with code that addresses software that is specific for your type of smart card and smart card reader. If you need to know more about external hashes and/or external signatures, consult the online how-to examples written by Paulo Soares: http://itextpdf.sourceforge.net/howtosign.html. If you want to know more about the Belgian eID, read my presentation notes for GovCamp Brussels: http://itext.ugent.be/articles/eid-pdf/.
© Copyright 2024