package org.jboss.seam.pdf.ui; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import javax.faces.context.FacesContext; import org.jboss.seam.pdf.ITextUtils; import org.jboss.seam.pdf.KeyStoreConfig; import org.jboss.seam.util.FacesResources; import org.jboss.seam.util.Resources; import com.lowagie.text.DocWriter; import com.lowagie.text.pdf.PdfAcroForm; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfSignatureAppearance; import com.lowagie.text.pdf.PdfStamper; import com.lowagie.text.pdf.PdfWriter; public class UISignature extends ITextComponent { // signature box String field; String size; String reason; String location; public void setField(String field) { this.field = field; } public void setSize(String size) { this.size = size; } public void setReason(String reason) { this.reason = reason; } public void setLocation(String location) { this.location = location; } @Override public void createITextObject(FacesContext context) { } @Override public void removeITextObject() { } @Override public Object getITextObject() { return null; } @Override public void handleAdd(Object other) { throw new RuntimeException("PDF signature does not accept children"); } @Override public void encodeEnd(FacesContext context) throws IOException { PdfWriter writer = findWriter(); if (writer == null) { throw new RuntimeException("Cannot find PdfWriter - the document may not exist or may not be a pdf type"); } PdfAcroForm form = writer.getAcroForm(); field = (String) valueBinding(context, "field", field); if (field == null) { throw new RuntimeException("signature field named is required"); } size = (String) valueBinding(context, "size", size); if (size == null) { throw new RuntimeException("signature size is required"); } float[] rect = ITextUtils.stringToFloatArray(size); if (rect.length != 4) { throw new RuntimeException("size must contain four numbers"); } form.addSignature(field, rect[0], rect[1], rect[2], rect[3]); UIDocument doc = (UIDocument) findITextParent(this, UIDocument.class); doc.addSignature(this); super.encodeEnd(context); } private PdfWriter findWriter() { UIDocument doc = (UIDocument) findITextParent(this, UIDocument.class); if (doc != null) { DocWriter writer = doc.getWriter(); if (writer instanceof PdfWriter) { return (PdfWriter) writer; } } return null; } public byte[] sign(byte[] originalBytes) { KeyStoreConfig store = KeyStoreConfig.instance(); InputStream is = null; try { is = FacesResources.getResourceAsStream(store.getKeyStore(), getFacesContext().getExternalContext()); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(is, store.getKeyStorePassword().toCharArray()); PrivateKey key = (PrivateKey) ks.getKey(store.getKeyAlias(), store.getKeyPassword().toCharArray()); Certificate[] chain = ks.getCertificateChain(store.getKeyAlias()); PdfReader reader = new PdfReader(originalBytes); ByteArrayOutputStream os = new ByteArrayOutputStream(); PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0'); PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setCrypto(key, chain, null, PdfSignatureAppearance.SELF_SIGNED); appearance.setReason(reason); appearance.setLocation(location); appearance.setVisibleSignature(field); stamper.close(); return os.toByteArray(); } catch (Exception e) { throw new RuntimeException(e); } finally { Resources.closeStream(is); } } }