Example usage for com.lowagie.text.pdf PdfSignatureAppearance CERTIFIED_NO_CHANGES_ALLOWED

List of usage examples for com.lowagie.text.pdf PdfSignatureAppearance CERTIFIED_NO_CHANGES_ALLOWED

Introduction

In this page you can find the example usage for com.lowagie.text.pdf PdfSignatureAppearance CERTIFIED_NO_CHANGES_ALLOWED.

Prototype

int CERTIFIED_NO_CHANGES_ALLOWED

To view the source code for com.lowagie.text.pdf PdfSignatureAppearance CERTIFIED_NO_CHANGES_ALLOWED.

Click Source Link

Usage

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);
    }
}