List of usage examples for com.lowagie.text.pdf PdfSignatureAppearance CERTIFIED_NO_CHANGES_ALLOWED
int CERTIFIED_NO_CHANGES_ALLOWED
To view the source code for com.lowagie.text.pdf PdfSignatureAppearance CERTIFIED_NO_CHANGES_ALLOWED.
Click Source Link
From source file:SignPdf.java
License:Open Source License
/** * Add a signature and a cryptographic timestamp to a pdf document. See www.ietf.org/rfc/rfc3161.txt. Proves that this * pdf had the current content at the current point in time. * * @param originalPdf/* ww w . j a v a 2 s . c o m*/ * @param targetPdf * @param pk * @param certChain * @param revoked * @param tsaAddress * address of a rfc 3161 compatible timestamp server * @param reason * reason for the signature * @param location * location of signing * @param contact * emailaddress of the person who is signing * @throws IOException * @throws DocumentException * @throws SignatureException */ public static void signAndTimestamp(final InputStream originalPdf, final OutputStream targetPdf, final PrivateKey pk, final X509Certificate[] certChain, final CRL[] revoked, final String tsaAddress, final String reason, final String location, final String contact) throws IOException, DocumentException, 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 Rectangle cropBox = reader.getCropBox(1); float width = 50; float height = 50; Rectangle rectangle = new Rectangle(cropBox.getRight(width) - 20, cropBox.getTop(height) - 20, cropBox.getRight() - 20, cropBox.getTop() - 20); sap.setVisibleSignature(rectangle, 1, null); //sap.setVisibleSignature(new Rectangle(450, 650, 500, 700), 1, null); sap.setLayer2Text(""); final PdfSigGenericPKCS sig = new PdfSigGenericPKCS.PPKMS("BC"); final HashMap<PdfName, Integer> exclusionSizes = new HashMap<PdfName, Integer>(); // some informational fields sig.setReason(reason); sig.setLocation(location); sig.setContact(contact); 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) try { 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(); byte[] ssig = pkcs7.getEncodedPKCS7(); try { // try to retrieve cryptographic timestamp from configured tsa server ssig = pkcs7.getEncodedPKCS7(null, null, new TSAClientBouncyCastle(tsaAddress), null); } catch (final RuntimeException e) { log.error("Could not retrieve timestamp from server.", e); } 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); } catch (final InvalidKeyException e) { throw new RuntimeException("Internal implementation error! No such signature type.", e); } catch (final NoSuchAlgorithmException e) { throw new RuntimeException("Internal implementation error! No such algorithm type.", e); } }
From source file:de.thorstenberger.examServer.pdf.signature.SignPdf.java
License:Open Source License
/** * Add a signature and a cryptographic timestamp to a pdf document. See www.ietf.org/rfc/rfc3161.txt. Proves that this * pdf had the current content at the current point in time. * * @param originalPdf/*from w w w . j a va2 s .c om*/ * @param targetPdf * @param pk * @param certChain * @param revoked * @param tsaAddress * address of a rfc 3161 compatible timestamp server * @param reason * reason for the signature * @param location * location of signing * @param contact * emailaddress of the person who is signing * @throws IOException * @throws DocumentException * @throws SignatureException */ public static void signAndTimestamp(final InputStream originalPdf, final OutputStream targetPdf, final PrivateKey pk, final X509Certificate[] certChain, final CRL[] revoked, final String tsaAddress, final String reason, final String location, final String contact) throws IOException, DocumentException, 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(450, 650, 500, 700), 1, null); sap.setLayer2Text(""); final PdfSigGenericPKCS sig = new PdfSigGenericPKCS.PPKMS("BC"); final HashMap<PdfName, Integer> exclusionSizes = new HashMap<PdfName, Integer>(); // some informational fields sig.setReason(reason); sig.setLocation(location); sig.setContact(contact); 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) try { 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(); byte[] ssig = pkcs7.getEncodedPKCS7(); try { // try to retrieve cryptographic timestamp from configured tsa server ssig = pkcs7.getEncodedPKCS7(null, null, new TSAClientBouncyCastle(tsaAddress), null); } catch (final RuntimeException e) { log.error("Could not retrieve timestamp from server.", e); } 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); } catch (final InvalidKeyException e) { throw new RuntimeException("Internal implementation error! No such signature type.", e); } catch (final NoSuchAlgorithmException e) { throw new RuntimeException("Internal implementation error! No such algorithm type.", e); } }
From source file:es.gob.afirma.signers.pades.PAdESSigner.java
License:Open Source License
@SuppressWarnings("boxing") static byte[] signPDF(final PrivateKey key, final java.security.cert.Certificate[] certChain, final byte[] inPDF, final Properties extraParams, final String algorithm) throws IOException, AOException, DocumentException, NoSuchAlgorithmException, CertificateException { // ********************************************************************************************************************* // **************** LECTURA PARAMETROS ADICIONALES ********************************************************************* // ********************************************************************************************************************* // Imagen de la rubrica final Image rubric = getRubricImage(extraParams.getProperty("signatureRubricImage")); //$NON-NLS-1$ // Usar hora y fecha del sistema final boolean useSystemDateTime = Boolean .parseBoolean(extraParams.getProperty("applySystemDate", Boolean.TRUE.toString())); //$NON-NLS-1$ // Motivo de la firma final String reason = extraParams.getProperty("signReason"); //$NON-NLS-1$ // Nombre del campo de firma preexistente en el PDF a usar final String signatureField = extraParams.getProperty("signatureField"); //$NON-NLS-1$ // Lugar de realizacion de la firma final String signatureProductionCity = extraParams.getProperty("signatureProductionCity"); //$NON-NLS-1$ // Datos de contacto (correo electronico) del firmante final String signerContact = extraParams.getProperty("signerContact"); //$NON-NLS-1$ // Pagina donde situar la firma visible int page = LAST_PAGE; try {/*from w ww . jav a 2 s . c o m*/ page = Integer.parseInt(extraParams.getProperty("signaturePage")); //$NON-NLS-1$ } catch (final Exception e) { /* Se deja la pagina tal y como esta */ } // Nombre del subfiltro de firma en el diccionario PDF final String signatureSubFilter = extraParams.getProperty("signatureSubFilter"); //$NON-NLS-1$ // ****************** // ** Adjuntos ****** // Contenido a adjuntar (en Base64) final String b64Attachment = extraParams.getProperty("attach"); //$NON-NLS-1$ // Nombre que se pondra al fichero adjunto en el PDF final String attachmentFileName = extraParams.getProperty("attachFileName"); //$NON-NLS-1$ // Descripcion del adjunto final String attachmentDescription = extraParams.getProperty("attachDescription"); //$NON-NLS-1$ // ** Fin Adjuntos ** // ****************** // Nivel de certificacion del PDF int certificationLevel; try { certificationLevel = extraParams.getProperty("certificationLevel") != null ? //$NON-NLS-1$ Integer.parseInt(extraParams.getProperty("certificationLevel")) : //$NON-NLS-1$ -1; } catch (final Exception e) { certificationLevel = UNDEFINED; } // ***************************** // **** Texto firma visible **** // Texto en capa 4 final String layer4Text = extraParams.getProperty("layer4Text"); //$NON-NLS-1$ // Texto en capa 2 final String layer2Text = extraParams.getProperty("layer2Text"); //$NON-NLS-1$ // Tipo de letra en capa 2 int layer2FontFamily; try { layer2FontFamily = extraParams.getProperty("layer2FontFamily") != null ? //$NON-NLS-1$ Integer.parseInt(extraParams.getProperty("layer2FontFamily")) : //$NON-NLS-1$ -1; } catch (final Exception e) { layer2FontFamily = UNDEFINED; } // Tamano del tipo de letra en capa 2 int layer2FontSize; try { layer2FontSize = extraParams.getProperty("layer2FontSize") != null ? //$NON-NLS-1$ Integer.parseInt(extraParams.getProperty("layer2FontSize")) : //$NON-NLS-1$ -1; } catch (final Exception e) { layer2FontSize = UNDEFINED; } // Estilo del tipo de letra en capa 2 int layer2FontStyle; try { layer2FontStyle = extraParams.getProperty("layer2FontStyle") != null ? //$NON-NLS-1$ Integer.parseInt(extraParams.getProperty("layer2FontStyle")) : //$NON-NLS-1$ -1; } catch (final Exception e) { layer2FontStyle = UNDEFINED; } // Color del tipo de letra en capa 2 final String layer2FontColor = extraParams.getProperty("layer2FontColor"); //$NON-NLS-1$ // ** Fin texto firma visible ** // ***************************** // Contrasena del propietario del PDF String ownerPassword = extraParams.getProperty("ownerPassword"); //$NON-NLS-1$ // Contrasena del usuario del PDF final String userPassword = extraParams.getProperty("userPassword"); //$NON-NLS-1$ // ********************************************************************************************************************* // **************** FIN LECTURA PARAMETROS ADICIONALES ***************************************************************** // ********************************************************************************************************************* PdfReader pdfReader; try { if (ownerPassword != null) { pdfReader = new PdfReader(inPDF, ownerPassword.getBytes()); } else if (userPassword != null) { pdfReader = new PdfReader(inPDF, userPassword.getBytes()); } else { pdfReader = new PdfReader(inPDF); } } catch (final BadPasswordException e) { // Comprobamos que el signer esta en modo interactivo, y si no lo // esta no pedimos contrasena por dialogo, principalmente para no interrumpir un firmado por lotes // desatendido if (Boolean.TRUE.toString().equalsIgnoreCase(extraParams.getProperty("headLess"))) { //$NON-NLS-1$ throw new BadPdfPasswordException(e); } // La contrasena que nos han proporcionada no es buena o no nos // proporcionaron ninguna ownerPassword = new String(AOUIFactory.getPassword( ownerPassword == null ? PDFMessages.getString("AOPDFSigner.0") //$NON-NLS-1$ : PDFMessages.getString("AOPDFSigner.1"), //$NON-NLS-1$ null)); try { pdfReader = new PdfReader(inPDF, ownerPassword.getBytes()); } catch (final BadPasswordException e2) { throw new BadPdfPasswordException(e2); } } catch (final IOException e) { throw new InvalidPdfException(e); } if (pdfReader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED && !Boolean.parseBoolean(extraParams.getProperty("allowSigningCertifiedPdfs"))) { //$NON-NLS-1$ // Si no permitimos dialogos graficos o directamente hemos indicado que no permitimos firmar PDF certificados lanzamos // una excepcion if (Boolean.parseBoolean(extraParams.getProperty("headLess")) //$NON-NLS-1$ || "false".equalsIgnoreCase(extraParams.getProperty("allowSigningCertifiedPdfs"))) { //$NON-NLS-1$ //$NON-NLS-2$ throw new PdfIsCertifiedException(); } // En otro caso, perguntamos al usuario if (AOUIFactory.NO_OPTION == AOUIFactory.showConfirmDialog(null, PDFMessages.getString("AOPDFSigner.8"), //$NON-NLS-1$ PDFMessages.getString("AOPDFSigner.9"), //$NON-NLS-1$ AOUIFactory.YES_NO_OPTION, AOUIFactory.WARNING_MESSAGE)) { throw new AOCancelledOperationException( "El usuario no ha permitido la firma de un PDF certificado"); //$NON-NLS-1$ } } // Los derechos van firmados por Adobe, y como desde iText se invalidan // es mejor quitarlos pdfReader.removeUsageRights(); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Activar el atributo de "agregar firma" (cuarto parametro del metodo // "PdfStamper.createSignature") hace que se cree una nueva revision del // documento y evita que las firmas previas queden invalidadas. Sin embargo, este // exige que el PDF no incorpore ningun error, asi que lo mantendremos desactivado // para la primera firma y activado para las subsiguientes. Un error incorporado // en un PDF erroneo puede quedar subsanado en su version firmada, haciendo // posible incorporar nuevas firmas agregando revisiones del documento. final PdfStamper stp; try { stp = PdfStamper.createSignature(pdfReader, // PDF de entrada baos, // Salida '\0', // Mantener version null, // No crear temporal pdfReader.getAcroFields().getSignatureNames().size() > 0 // Si hay mas firmas, creo una revision ); } catch (final BadPasswordException e) { throw new PdfIsPasswordProtectedException(e); } // Aplicamos todos los atributos de firma final PdfSignatureAppearance sap = stp.getSignatureAppearance(); stp.setFullCompression(); sap.setAcro6Layers(true); // PAdES parte 3 seccion 4.7 - Habilitacion para LTV stp.getWriter().addDeveloperExtension(new PdfDeveloperExtension(new PdfName("ESIC"), //$NON-NLS-1$ PdfWriter.PDF_VERSION_1_7, 1)); // Adjuntos if (b64Attachment != null && attachmentFileName != null) { byte[] attachment = null; try { attachment = Base64.decode(b64Attachment); } catch (final IOException e) { LOGGER.warning("Se ha indicado un adjunto, pero no estaba en formato Base64, se ignorara : " + e); //$NON-NLS-1$ } if (attachment != null) { stp.getWriter().addFileAttachment(attachmentDescription, attachment, null, attachmentFileName); } } // iText antiguo sap.setRender(PdfSignatureAppearance.SignatureRenderDescription); // En iText nuevo seria "sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION);" // Razon de firma if (reason != null) { sap.setReason(reason); } // Establecer fecha local del equipo if (useSystemDateTime) { sap.setSignDate(new GregorianCalendar()); } // Gestion de los cifrados if (pdfReader.isEncrypted() && (ownerPassword != null || userPassword != null)) { if (Boolean.TRUE.toString().equalsIgnoreCase(extraParams.getProperty("avoidEncryptingSignedPdfs"))) { //$NON-NLS-1$ LOGGER.info( "Aunque el PDF original estaba encriptado no se encriptara el PDF firmado (se establecio el indicativo 'avoidEncryptingSignedPdfs')" //$NON-NLS-1$ ); } else { LOGGER.info("El PDF original estaba encriptado, se intentara encriptar tambien el PDF firmado" //$NON-NLS-1$ ); try { stp.setEncryption(ownerPassword != null ? ownerPassword.getBytes() : null, userPassword != null ? userPassword.getBytes() : null, pdfReader.getPermissions(), pdfReader.getCryptoMode()); } catch (final DocumentException de) { LOGGER.warning("No se ha podido cifrar el PDF destino, se escribira sin contrasena: " + de //$NON-NLS-1$ ); } } } // Pagina en donde se imprime la firma if (page == LAST_PAGE) { page = pdfReader.getNumberOfPages(); } // Posicion de la firma final Rectangle signaturePositionOnPage = getSignaturePositionOnPage(extraParams); if (signaturePositionOnPage != null && signatureField == null) { sap.setVisibleSignature(signaturePositionOnPage, page, null); } else if (signatureField != null) { sap.setVisibleSignature(signatureField); } // Localizacion en donde se produce la firma if (signatureProductionCity != null) { sap.setLocation(signatureProductionCity); } // Contacto del firmante if (signerContact != null) { sap.setContact(signerContact); } // Rubrica de la firma if (rubric != null) { sap.setImage(rubric); sap.setLayer2Text(""); //$NON-NLS-1$ sap.setLayer4Text(""); //$NON-NLS-1$ } // ************************** // ** Texto en las capas **** // ************************** // Capa 2 if (layer2Text != null) { sap.setLayer2Text(layer2Text); final int layer2FontColorR; final int layer2FontColorG; final int layer2FontColorB; if ("black".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 0; layer2FontColorG = 0; layer2FontColorB = 0; } else if ("white".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 255; layer2FontColorG = 255; layer2FontColorB = 255; } else if ("lightGray".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 192; layer2FontColorG = 192; layer2FontColorB = 192; } else if ("gray".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 128; layer2FontColorG = 128; layer2FontColorB = 128; } else if ("darkGray".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 64; layer2FontColorG = 64; layer2FontColorB = 64; } else if ("red".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 255; layer2FontColorG = 0; layer2FontColorB = 0; } else if ("pink".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$ layer2FontColorR = 255; layer2FontColorG = 175; layer2FontColorB = 175; } else if (layer2FontColor == null) { layer2FontColorR = 0; layer2FontColorG = 0; layer2FontColorB = 0; } else { LOGGER.warning("No se soporta el color '" + layer2FontColor //$NON-NLS-1$ + "' para el texto de la capa 4, se usara negro"); //$NON-NLS-1$ layer2FontColorR = 0; layer2FontColorG = 0; layer2FontColorB = 0; } com.lowagie.text.Font font; try { Class<?> colorClass; if (Platform.getOS() == OS.ANDROID) { colorClass = Class.forName("harmony.java.awt.Color"); //$NON-NLS-1$ } else { colorClass = Class.forName("java.awt.Color"); //$NON-NLS-1$ } final Object color = colorClass.getConstructor(Integer.TYPE, Integer.TYPE, Integer.TYPE) .newInstance(layer2FontColorR, layer2FontColorG, layer2FontColorB); font = com.lowagie.text.Font.class .getConstructor(Integer.TYPE, Integer.TYPE, Integer.TYPE, colorClass).newInstance( // Family (COURIER = 0, HELVETICA = 1, TIMES_ROMAN = 2, SYMBOL = 3, ZAPFDINGBATS = 4) layer2FontFamily == UNDEFINED ? COURIER : layer2FontFamily, // Size (DEFAULTSIZE = 12) layer2FontSize == UNDEFINED ? DEFAULT_LAYER_2_FONT_SIZE : layer2FontSize, // Style (NORMAL = 0, BOLD = 1, ITALIC = 2, BOLDITALIC = 3, UNDERLINE = 4, STRIKETHRU = 8) layer2FontStyle == UNDEFINED ? com.lowagie.text.Font.NORMAL : layer2FontStyle, // Color color); } catch (Exception e) { font = new com.lowagie.text.Font( // Family (COURIER = 0, HELVETICA = 1, TIMES_ROMAN = 2, SYMBOL = 3, ZAPFDINGBATS = 4) layer2FontFamily == UNDEFINED ? COURIER : layer2FontFamily, // Size (DEFAULTSIZE = 12) layer2FontSize == UNDEFINED ? DEFAULT_LAYER_2_FONT_SIZE : layer2FontSize, // Style (NORMAL = 0, BOLD = 1, ITALIC = 2, BOLDITALIC = 3, UNDERLINE = 4, STRIKETHRU = 8) layer2FontStyle == UNDEFINED ? com.lowagie.text.Font.NORMAL : layer2FontStyle, // Color null); } sap.setLayer2Font(font); } // Capa 4 if (layer4Text != null) { sap.setLayer4Text(layer4Text); } // *************************** // ** Fin texto en las capas * // *************************** sap.setCrypto(null, certChain, null, null); final PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, signatureSubFilter != null && !"".equals(signatureSubFilter) ? new PdfName(signatureSubFilter) //$NON-NLS-1$ : PdfName.ADBE_PKCS7_DETACHED); // Fecha de firma if (sap.getSignDate() != null) { dic.setDate(new PdfDate(sap.getSignDate())); } dic.setName(PdfPKCS7.getSubjectFields((X509Certificate) certChain[0]).getField("CN")); //$NON-NLS-1$ if (sap.getReason() != null) { dic.setReason(sap.getReason()); } // Lugar de la firma if (sap.getLocation() != null) { dic.setLocation(sap.getLocation()); } // Contacto del firmante if (sap.getContact() != null) { dic.setContact(sap.getContact()); } sap.setCryptoDictionary(dic); // Certificacion del PDF (NOT_CERTIFIED = 0, CERTIFIED_NO_CHANGES_ALLOWED = 1, // CERTIFIED_FORM_FILLING = 2, CERTIFIED_FORM_FILLING_AND_ANNOTATIONS = 3) if (certificationLevel != -1) { sap.setCertificationLevel(certificationLevel); } // Reservamos el espacio necesario en el PDF para insertar la firma final HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>(); exc.put(PdfName.CONTENTS, Integer.valueOf(CSIZE * 2 + 2)); sap.preClose(exc); // ******************************************************************************** // **************** CALCULO DEL SIGNED DATA *************************************** // ******************************************************************************** // La norma PAdES establece que si el algoritmo de huella digital es SHA1 debe usarse SigningCertificateV2, y en cualquier // otro caso deberia usarse SigningCertificateV2 boolean signingCertificateV2; if (extraParams.containsKey("signingCertificateV2")) { //$NON-NLS-1$ signingCertificateV2 = Boolean.parseBoolean(extraParams.getProperty("signingCertificateV2")); //$NON-NLS-1$ } else { signingCertificateV2 = !"SHA1".equals(AOSignConstants.getDigestAlgorithmName(algorithm)); //$NON-NLS-1$ } byte[] completeCAdESSignature = GenCAdESEPESSignedData.generateSignedData( new P7ContentSignerParameters(inPDF, algorithm), true, // omitContent new AdESPolicy(extraParams), signingCertificateV2, key, certChain, MessageDigest.getInstance(AOSignConstants.getDigestAlgorithmName(algorithm)) .digest(AOUtil.getDataFromInputStream(sap.getRangeStream())), AOSignConstants.getDigestAlgorithmName(algorithm), true, // Modo PAdES PDF_OID, extraParams.getProperty("contentDescription") != null //$NON-NLS-1$ ? extraParams.getProperty("contentDescription") //$NON-NLS-1$ : PDF_DESC); //***************** SELLO DE TIEMPO **************** final String tsa = extraParams.getProperty("tsaURL"); //$NON-NLS-1$ URI tsaURL; if (tsa != null) { try { tsaURL = new URI(tsa); } catch (final Exception e) { LOGGER.warning("Se ha indicado una URL de TSA invalida (" + tsa //$NON-NLS-1$ + "), no se anadira sello de tiempo: " + e); //$NON-NLS-1$ tsaURL = null; } if (tsaURL != null) { final String tsaPolicy = extraParams.getProperty("tsaPolicy"); //$NON-NLS-1$ if (tsaPolicy == null) { LOGGER.warning( "Se ha indicado una URL de TSA pero no una politica, no se anadira sello de tiempo"); //$NON-NLS-1$ } else { final String tsaHashAlgorithm = extraParams.getProperty("tsaHashAlgorithm"); //$NON-NLS-1$ completeCAdESSignature = new CMSTimestamper( !Boolean.FALSE.toString().equalsIgnoreCase(extraParams.getProperty("tsaRequireCert")), //$NON-NLS-1$ tsaPolicy, tsaURL, extraParams.getProperty("tsaUsr"), //$NON-NLS-1$ extraParams.getProperty("tsaPwd"), //$NON-NLS-1$ extraParams.getProperty("tsaExtensionOid") != null //$NON-NLS-1$ && extraParams.getProperty("tsaExtensionValueBase64") != null ? //$NON-NLS-1$ new TsaRequestExtension[] { new TsaRequestExtension( extraParams.getProperty("tsaExtensionOid"), //$NON-NLS-1$ Boolean.getBoolean(extraParams .getProperty("tsaExtensionCritical", "false")), //$NON-NLS-1$ //$NON-NLS-2$ Base64.decode( extraParams.getProperty("tsaExtensionValueBase64")) //$NON-NLS-1$ ) } : null).addTimestamp(completeCAdESSignature, AOAlgorithmID.getOID(AOSignConstants.getDigestAlgorithmName( tsaHashAlgorithm != null ? tsaHashAlgorithm : "SHA1"))); //$NON-NLS-1$ } } } //************** FIN SELLO DE TIEMPO **************** // ******************************************************************************** // *************** FIN CALCULO DEL SIGNED DATA ************************************ // ******************************************************************************** final byte[] outc = new byte[CSIZE]; if (outc.length < completeCAdESSignature.length) { throw new AOException("La firma generada tiene un tamano (" + completeCAdESSignature.length //$NON-NLS-1$ + ") mayor que el permitido (" + outc.length + ")" //$NON-NLS-1$ //$NON-NLS-2$ ); } final PdfDictionary dic2 = new PdfDictionary(); System.arraycopy(completeCAdESSignature, 0, outc, 0, completeCAdESSignature.length); dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true)); sap.close(dic2); return baos.toByteArray(); }
From source file:net.sf.jsignpdf.verify.SignatureVerification.java
License:Mozilla Public License
/** * Gets validation code for this verification * /*from www. ja v a 2 s . c o m*/ * @return validation code defined in {@link SignatureVerification} */ public int getValidationCode() { int code = SignatureVerification.SIG_STAT_CODE_INFO_SIGNATURE_VALID; // TODO Handle case when OCRL checking fails // TODO Handle case when new content is added after signature with // certification level set if (isModified()) { // ERROR: signed revision is altered code = SignatureVerification.SIG_STAT_CODE_ERROR_REVISION_MODIFIED; } else if (!isLastSignature && getCertLevelCode() == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED) { // ERROR: some signature has certification level set but document is // changed (at least with some additional signatures) code = SignatureVerification.SIG_STAT_CODE_ERROR_CERTIFICATION_BROKEN; } else if (isLastSignature && !isWholeDocument() && getCertLevelCode() != PdfSignatureAppearance.NOT_CERTIFIED) { // TODO What if e.g. annotations are added (which is allowed by cert // level)? // ERROR: last signature doesn't cover whole document (document is // changed) and certification level set code = SignatureVerification.SIG_STAT_CODE_ERROR_CERTIFICATION_BROKEN; } else if (isLastSignature && !isWholeDocument()) { // WARNING: last signature doesn't cover whole document - there is // some unsigned content in the document code = SignatureVerification.SIG_STAT_CODE_WARNING_UNSIGNED_CONTENT; } else if (!isSignCertTrustedAndValid() && getFails() != null) { // WARNING: there is some problem with certificate String errorMessage = String.valueOf(getFails()[1]).trim().toLowerCase(); if (errorMessage.startsWith(CERT_PROBLEM_CANT_BE_VERIFIED.trim().toLowerCase())) { // WARNING: certificate is not trusted (can't be verified // against keystore) code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_CANT_BE_VERIFIED; } else if (errorMessage.startsWith(CERT_PROBLEM_EXPIRED.trim().toLowerCase())) { // WARNING: certificate expired code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_EXPIRED; } else if (errorMessage.startsWith(CERT_PROBLEM_NOT_YET_VALID.trim().toLowerCase())) { // WARNING: certificate not yet valid code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_NOT_YET_VALID; } else if (errorMessage.startsWith(CERT_PROBLEM_REVOKED.trim().toLowerCase())) { // WARNING: certificate revoked code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_REVOKED; } else if (errorMessage.startsWith(CERT_PROBLEM_UNSUPPORTED_CRITICAL_EXTENSION.trim().toLowerCase())) { // WARNING: certificate has unsupported critical extension code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_UNSUPPORTED_CRITICAL_EXTENSION; } else if (errorMessage.startsWith(CERT_PROBLEM_INVALID_STATE.trim().toLowerCase())) { // WARNING: possible circular certificate chain code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_INVALID_STATE; } else { // WARNING: some other certificate error code = SignatureVerification.SIG_STAT_CODE_WARNING_CERTIFICATE_PROBLEM; } } else if ((!isCrlPresent() || (isCrlPresent() && getFails() != null)) && !isSignCertTrustedAndValid() && (isOcspPresent() || isOcspInCertPresent()) && !isOcspValid() && !isOcspInCertValid()) { // If certificate is successfully validated against CRL - don't set // warning flag for OCSP (set OCSP error only if CRL doesn't exist // or there are some errors) // WARNING: OCSP validation fails code = SignatureVerification.SIG_STAT_CODE_WARNING_SIGNATURE_OCSP_INVALID; } else if (!isSignCertTrustedAndValid() && !isOcspPresent() && !isOcspInCertPresent() && !isCrlPresent()) { // WARNING: No revocation information (CRL or OCSP) found code = SignatureVerification.SIG_STAT_CODE_WARNING_NO_REVOCATION_INFO; } else if (!isTsTokenPresent()) { // WARNING: signature date/time are from the clock on the signer's // computer code = SignatureVerification.SIG_STAT_CODE_WARNING_NO_TIMESTAMP_TOKEN; } else if (isTsTokenPresent() && getTsTokenValidationResult() != null) { // WARNING: signature is timestamped but the timestamp could not be // verified code = SignatureVerification.SIG_STAT_CODE_WARNING_TIMESTAMP_INVALID; } return code; }
From source file:org.signserver.module.pdfsigner.PDFSigner.java
License:Open Source License
protected byte[] addSignatureToPDFDocument(final ICryptoInstance crypto, PDFSignerParameters params, byte[] pdfbytes, byte[] password, int contentEstimated, final ProcessRequest request, final RequestContext context) throws IOException, DocumentException, CryptoTokenOfflineException, SignServerException, IllegalRequestException { // when given a content length (i.e. non-zero), it means we are running a second try boolean secondTry = contentEstimated != 0; // get signing cert certificate chain and private key final List<Certificate> certs = getSigningCertificateChain(crypto); if (certs == null) { throw new SignServerException("Null certificate chain. This signer needs a certificate."); }/* ww w.j a v a 2 s . co m*/ final List<Certificate> includedCerts = includedCertificates(certs); Certificate[] certChain = includedCerts.toArray(new Certificate[includedCerts.size()]); PrivateKey privKey = crypto.getPrivateKey(); // need to check digest algorithms for DSA private key at signing // time since we can't be sure what key a configured alias selector gives back if (privKey instanceof DSAPrivateKey) { if (!"SHA1".equals(digestAlgorithm)) { throw new IllegalRequestException( "Only SHA1 is permitted as digest algorithm for DSA private keys"); } } PdfReader reader = new PdfReader(pdfbytes, password); boolean appendMode = true; // TODO: This could be good to have as a property in the future int pdfVersion; try { pdfVersion = Integer.parseInt(Character.toString(reader.getPdfVersion())); } catch (NumberFormatException e) { pdfVersion = 0; } if (LOG.isDebugEnabled()) { LOG.debug("PDF version: " + pdfVersion); } // Don't certify already certified documents if (reader.getCertificationLevel() != PdfSignatureAppearance.NOT_CERTIFIED && params.getCertification_level() != PdfSignatureAppearance.NOT_CERTIFIED) { throw new IllegalRequestException("Will not certify an already certified document"); } // Don't sign documents where the certification does not allow it if (reader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED || reader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_FORM_FILLING) { throw new IllegalRequestException("Will not sign a certified document where signing is not allowed"); } Permissions currentPermissions = Permissions.fromInt(reader.getPermissions()); if (params.getSetPermissions() != null && params.getRemovePermissions() != null) { throw new SignServerException("Signer " + workerId + " missconfigured. Only one of " + SET_PERMISSIONS + " and " + REMOVE_PERMISSIONS + " should be specified."); } Permissions newPermissions; if (params.getSetPermissions() != null) { newPermissions = params.getSetPermissions(); } else if (params.getRemovePermissions() != null) { newPermissions = currentPermissions.withRemoved(params.getRemovePermissions()); } else { newPermissions = null; } Permissions rejectPermissions = Permissions.fromSet(params.getRejectPermissions()); byte[] userPassword = reader.computeUserPassword(); int cryptoMode = reader.getCryptoMode(); if (LOG.isDebugEnabled()) { StringBuilder buff = new StringBuilder(); buff.append("Current permissions: ").append(currentPermissions).append("\n") .append("Remove permissions: ").append(params.getRemovePermissions()).append("\n") .append("Reject permissions: ").append(rejectPermissions).append("\n") .append("New permissions: ").append(newPermissions).append("\n").append("userPassword: ") .append(userPassword == null ? "null" : "yes").append("\n").append("ownerPassword: ") .append(password == null ? "no" : (isUserPassword(reader, password) ? "no" : "yes")) .append("\n").append("setOwnerPassword: ") .append(params.getSetOwnerPassword() == null ? "no" : "yes").append("\n").append("cryptoMode: ") .append(cryptoMode); LOG.debug(buff.toString()); } if (appendMode && (newPermissions != null || params.getSetOwnerPassword() != null)) { appendMode = false; if (LOG.isDebugEnabled()) { LOG.debug("Changing appendMode to false to be able to change permissions"); } } ByteArrayOutputStream fout = new ByteArrayOutputStream(); // increase PDF version if needed by digest algorithm final char updatedPdfVersion; if (minimumPdfVersion > pdfVersion) { updatedPdfVersion = Character.forDigit(minimumPdfVersion, 10); if (LOG.isDebugEnabled()) { LOG.debug("Need to upgrade PDF to version 1." + updatedPdfVersion); } // check that the document isn't already signed // when trying to upgrade version final AcroFields af = reader.getAcroFields(); final List<String> sigNames = af.getSignatureNames(); if (!sigNames.isEmpty()) { // TODO: in the future we might want to support // a fallback option in this case to allow re-signing using the same version (using append) throw new IllegalRequestException( "Can not upgrade an already signed PDF and a higher version is required to support the configured digest algorithm"); } appendMode = false; } else { updatedPdfVersion = '\0'; } PdfStamper stp = PdfStamper.createSignature(reader, fout, updatedPdfVersion, null, appendMode); PdfSignatureAppearance sap = stp.getSignatureAppearance(); // Set the new permissions if (newPermissions != null || params.getSetOwnerPassword() != null) { if (cryptoMode < 0) { cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128; if (LOG.isDebugEnabled()) { LOG.debug("Setting default encryption algorithm"); } } if (newPermissions == null) { newPermissions = currentPermissions; } if (params.getSetOwnerPassword() != null) { password = params.getSetOwnerPassword().getBytes("ISO-8859-1"); } else if (isUserPassword(reader, password)) { // We do not have an owner password so lets use a random one password = new byte[16]; random.nextBytes(password); if (LOG.isDebugEnabled()) { LOG.debug("Setting random owner password"); } } stp.setEncryption(userPassword, password, newPermissions.asInt(), cryptoMode); currentPermissions = newPermissions; } // Reject if any permissions are rejected and the document does not use a permission password // or if it contains any of the rejected permissions if (rejectPermissions.asInt() != 0) { if (cryptoMode < 0 || currentPermissions.containsAnyOf(rejectPermissions)) { throw new IllegalRequestException("Document contains permissions not allowed by this signer"); } } // include signer certificate crl inside cms package if requested CRL[] crlList = null; if (params.isEmbed_crl()) { crlList = getCrlsForChain(certs); } sap.setCrypto(null, certChain, crlList, PdfSignatureAppearance.SELF_SIGNED); // add visible signature if requested if (params.isAdd_visible_signature()) { int signaturePage = getPageNumberForSignature(reader, params); sap.setVisibleSignature(new com.lowagie.text.Rectangle(params.getVisible_sig_rectangle_llx(), params.getVisible_sig_rectangle_lly(), params.getVisible_sig_rectangle_urx(), params.getVisible_sig_rectangle_ury()), signaturePage, null); // set custom image if requested if (params.isUse_custom_image()) { sap.setAcro6Layers(true); PdfTemplate n2 = sap.getLayer(2); params.getCustom_image().setAbsolutePosition(0, 0); n2.addImage(params.getCustom_image()); } } // Certification level sap.setCertificationLevel(params.getCertification_level()); PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached")); dic.setReason(params.getReason()); dic.setLocation(params.getLocation()); dic.setDate(new PdfDate(Calendar.getInstance())); sap.setCryptoDictionary(dic); // add timestamp to signature if requested TSAClient tsc = null; if (params.isUse_timestamp()) { final String tsaUrl = params.getTsa_url(); if (tsaUrl != null) { tsc = getTimeStampClient(params.getTsa_url(), params.getTsa_username(), params.getTsa_password()); } else { tsc = new InternalTSAClient(getWorkerSession(), params.getTsa_worker(), params.getTsa_username(), params.getTsa_password()); } } // embed ocsp response in cms package if requested // for ocsp request to be formed there needs to be issuer certificate in // chain byte[] ocsp = null; if (params.isEmbed_ocsp_response() && certChain.length >= 2) { String url; try { url = PdfPKCS7.getOCSPURL((X509Certificate) certChain[0]); if (url != null && url.length() > 0) { ocsp = new OcspClientBouncyCastle((X509Certificate) certChain[0], (X509Certificate) certChain[1], url).getEncoded(); } } catch (CertificateParsingException e) { throw new SignServerException("Error getting OCSP URL from certificate", e); } } PdfPKCS7 sgn; try { sgn = new PdfPKCS7(privKey, certChain, crlList, digestAlgorithm, null, false); } catch (InvalidKeyException e) { throw new SignServerException("Error constructing PKCS7 package", e); } catch (NoSuchProviderException e) { throw new SignServerException("Error constructing PKCS7 package", e); } catch (NoSuchAlgorithmException e) { throw new SignServerException("Error constructing PKCS7 package", e); } MessageDigest messageDigest; try { messageDigest = MessageDigest.getInstance(digestAlgorithm); } catch (NoSuchAlgorithmException e) { throw new SignServerException("Error creating " + digestAlgorithm + " digest", e); } Calendar cal = Calendar.getInstance(); // calculate signature size if (contentEstimated == 0) { contentEstimated = calculateEstimatedSignatureSize(certChain, tsc, ocsp, crlList); } byte[] encodedSig = calculateSignature(sgn, contentEstimated, messageDigest, cal, params, certChain, tsc, ocsp, sap); if (LOG.isDebugEnabled()) { LOG.debug("Estimated size: " + contentEstimated); LOG.debug("Encoded length: " + encodedSig.length); } if (contentEstimated + 2 < encodedSig.length) { if (!secondTry) { int contentExact = encodedSig.length; LOG.warn( "Estimated signature size too small, usinging accurate calculation (resulting in an extra signature computation)."); if (LOG.isDebugEnabled()) { LOG.debug("Estimated size: " + contentEstimated + ", actual size: " + contentExact); } // try signing again return addSignatureToPDFDocument(crypto, params, pdfbytes, password, contentExact, request, context); } else { // if we fail to get an accurate signature size on the second attempt, bail out (this shouldn't happen) throw new SignServerException("Failed to calculate signature size"); } } byte[] paddedSig = new byte[contentEstimated]; System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length); PdfDictionary dic2 = new PdfDictionary(); dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true)); sap.close(dic2); reader.close(); fout.close(); return fout.toByteArray(); }
From source file:org.signserver.module.pdfsigner.PDFSignerParameters.java
License:Open Source License
private void extractAndProcessConfigurationProperties() throws IllegalRequestException, SignServerException { // The reason shown in the PDF signature if (config.getProperties().getProperty(PDFSigner.REASON) != null) { reason = config.getProperties().getProperty(PDFSigner.REASON); }/* ww w . j a va 2s.co m*/ LOG.debug("Using reason: " + reason); // The location shown in the PDF signature if (config.getProperties().getProperty(PDFSigner.LOCATION) != null) { location = config.getProperties().getProperty(PDFSigner.LOCATION); } LOG.debug("Using location: " + location); // are we adding visible or invisible signature // note : ParseBoolean returns false for everything but "True" if (config.getProperties().getProperty(PDFSigner.ADD_VISIBLE_SIGNATURE) != null) { add_visible_signature = Boolean .parseBoolean(config.getProperties().getProperty(PDFSigner.ADD_VISIBLE_SIGNATURE).trim()); } LOG.debug("Using visible signature: " + add_visible_signature); // timestamp url if (config.getProperties().getProperty(PDFSigner.TSA_URL) != null) { tsa_url = config.getProperties().getProperty(PDFSigner.TSA_URL); use_timestamp = true; LOG.debug("Using tsa url : " + tsa_url); } else if (config.getProperties().getProperty(PDFSigner.TSA_WORKER) != null) { tsa_worker = config.getProperties().getProperty(PDFSigner.TSA_WORKER); use_timestamp = true; } if (use_timestamp && config.getProperties().getProperty(PDFSigner.TSA_USERNAME) != null && config.getProperties().getProperty(PDFSigner.TSA_PASSWORD) != null) { tsa_username = config.getProperties().getProperty(PDFSigner.TSA_USERNAME); tsa_password = config.getProperties().getProperty(PDFSigner.TSA_PASSWORD); use_timestamp_authorization = true; } // should we embed crl inside the cms package if (config.getProperties().getProperty(PDFSigner.EMBED_CRL) != null) { embed_crl = Boolean.parseBoolean(config.getProperties().getProperty(PDFSigner.EMBED_CRL).trim()); } LOG.debug("Using embed crl inside cms package : " + isEmbed_crl()); // should we embed ocsp response inside the cms package if (config.getProperties().getProperty(PDFSigner.EMBED_OCSP_RESPONSE) != null) { embed_ocsp_response = Boolean .parseBoolean(config.getProperties().getProperty(PDFSigner.EMBED_OCSP_RESPONSE).trim()); } LOG.debug("Using embed ocsp inside cms package : " + isEmbed_ocsp_response()); // should we refuse PDF documents that contains multiple // indirect objects with the same name if (config.getProperties().getProperty(PDFSigner.REFUSE_DOUBLE_INDIRECT_OBJECTS) != null) { refuseDoubleIndirectObjects = Boolean .parseBoolean(config.getProperties().getProperty(PDFSigner.REFUSE_DOUBLE_INDIRECT_OBJECTS)); } // Reject permissions String rejectPermissionsValue = config.getProperties().getProperty(PDFSigner.REJECT_PERMISSIONS); if (rejectPermissionsValue != null) { String[] array = rejectPermissionsValue.split(","); rejectPermissions.addAll(Arrays.asList(array)); } // Set permissions String setPermissionsValue = config.getProperties().getProperty(PDFSigner.SET_PERMISSIONS); if (setPermissionsValue != null) { String[] array = setPermissionsValue.split(","); try { setPermissions = Permissions.fromSet(Arrays.asList(array), true); } catch (UnknownPermissionException ex) { throw new SignServerException("Signer " + workerId + " missconfigured: " + ex.getMessage()); } } // Remove permissions String removePermissionsValue = config.getProperties().getProperty(PDFSigner.REMOVE_PERMISSIONS); if (removePermissionsValue != null) { String[] array = removePermissionsValue.split(","); removePermissions = new HashSet<String>(); removePermissions.addAll(Arrays.asList(array)); } // Set ownerpassword setOwnerPassword = config.getProperties().getProperty(PDFSigner.SET_OWNERPASSWORD); // if signature is chosen to be visible proceed with setting visibility // properties if (add_visible_signature) { // page to draw visible signature at if (config.getProperties().getProperty(PDFSigner.VISIBLE_SIGNATURE_PAGE) != null) { visible_sig_page = config.getProperties().getProperty(PDFSigner.VISIBLE_SIGNATURE_PAGE); } LOG.debug("Using visible signature page: " + visible_sig_page); // The location of the visible signature rectangle(llx, lly, urx, // ury) // llx = lower left x coordinate, lly = lower left y coordinate, urx // = upper right x coordinate, ury = upper right y coordinate if (config.getProperties().getProperty(PDFSigner.VISIBLE_SIGNATURE_RECTANGLE) != null) { visible_sig_rectangle = config.getProperties().getProperty(PDFSigner.VISIBLE_SIGNATURE_RECTANGLE); } LOG.debug("Using rectangle: " + visible_sig_rectangle); String[] rect = visible_sig_rectangle.split(","); if (rect.length < 4) { throw new IllegalRequestException( "RECTANGLE property must contain 4 comma separated values with no spaces."); } visible_sig_rectangle_llx = Integer.valueOf(rect[0]); visible_sig_rectangle_lly = Integer.valueOf(rect[1]); visible_sig_rectangle_urx = Integer.valueOf(rect[2]); visible_sig_rectangle_ury = Integer.valueOf(rect[3]); // custom image to use with signature // base64 encoded byte[] if (config.getProperties().getProperty(PDFSigner.VISIBLE_SIGNATURE_CUSTOM_IMAGE_BASE64) != null) { visible_sig_custom_image_base64 = config.getProperties() .getProperty(PDFSigner.VISIBLE_SIGNATURE_CUSTOM_IMAGE_BASE64); LOG.debug("base64 encoded custom image is set"); } // custom image path. Do not set if base64 encoded image is // specified if (visible_sig_custom_image_base64 == null || visible_sig_custom_image_base64.isEmpty()) { if (config.getProperties().getProperty(PDFSigner.VISIBLE_SIGNATURE_CUSTOM_IMAGE_PATH) != null) { visible_sig_custom_image_path = config.getProperties() .getProperty(PDFSigner.VISIBLE_SIGNATURE_CUSTOM_IMAGE_PATH); LOG.debug("using custom image path : " + visible_sig_custom_image_path); } } boolean use_image_from_base64_string = visible_sig_custom_image_base64 != null && !visible_sig_custom_image_base64.isEmpty(); boolean use_image_from_path = visible_sig_custom_image_path != null && !visible_sig_custom_image_path.isEmpty(); use_custom_image = use_image_from_base64_string || use_image_from_path; // custom image resizing (if we are using custom image) if (use_custom_image) { // retrieve custom image byte[] imageByteArray; if (use_image_from_base64_string) { imageByteArray = Base64.decode(visible_sig_custom_image_base64.getBytes()); } else { try { imageByteArray = readFile(visible_sig_custom_image_path); } catch (IOException e) { throw new SignServerException("Error reading custom image data from path specified", e); } } try { custom_image = Image.getInstance(imageByteArray); } catch (BadElementException e) { throw new SignServerException("Problem constructing image from custom image data", e); } catch (MalformedURLException e) { throw new SignServerException("Problem constructing image from custom image data", e); } catch (IOException e) { throw new SignServerException("Problem constructing image from custom image data", e); } if (config.getProperties() .getProperty(PDFSigner.VISIBLE_SIGNATURE_CUSTOM_IMAGE_SCALE_TO_RECTANGLE) != null) { visible_sig_custom_image_scale_to_rectangle = Boolean.parseBoolean(config.getProperties() .getProperty(PDFSigner.VISIBLE_SIGNATURE_CUSTOM_IMAGE_SCALE_TO_RECTANGLE).trim()); LOG.debug("resize custom image to rectangle : " + visible_sig_custom_image_scale_to_rectangle); } // if we are using custom image and the // VISIBLE_SIGNATURE_CUSTOM_IMAGE_SCALE_TO_RECTANGLE is set to // true resize image to fit to rectangle specified // If set to false calculate urx and ury coordinates from image if (visible_sig_custom_image_scale_to_rectangle) { resizeImageToFitToRectangle(); } else { calculateUpperRightRectangleCoordinatesFromImage(); } } } // Certification level final String level = config.getProperty(PDFSigner.CERTIFICATION_LEVEL); if (level != null) { if (level.equalsIgnoreCase("NO_CHANGES_ALLOWED")) { certification_level = PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED; } else if (level.equalsIgnoreCase("FORM_FILLING_AND_ANNOTATIONS")) { certification_level = PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS; } else if (level.equalsIgnoreCase("FORM_FILLING")) { certification_level = PdfSignatureAppearance.CERTIFIED_FORM_FILLING; } else if (level.equalsIgnoreCase("NOT_CERTIFIED")) { certification_level = PdfSignatureAppearance.NOT_CERTIFIED; } else { throw new SignServerException("Unknown value for CERTIFICATION_LEVEL"); } } if (LOG.isDebugEnabled()) { LOG.debug("using certification level: " + certification_level); } }