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

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

Introduction

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

Prototype

public void setCrypto(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, PdfName filter) 

Source Link

Document

Sets the cryptographic parameters.

Usage

From source file:androidGLUESigner.pdf.PDFSignerEngine.java

License:Open Source License

/**
 * Prepare the signing of the pdf (siganture appearance, placeholders, sigimage, ..) 
 * @param inputStream the stream to the input pdf file
 * @param outputStream the stream to the output pdf file
 * @return hash value with ocsp included
 * @throws IOException//w  ww  .  ja v  a 2 s. com
 * @throws DocumentException
 * @throws GeneralSecurityException
 */
public byte[] prepareSign(InputStream inputStream, OutputStream outputStream)
        throws IOException, DocumentException, GeneralSecurityException {

    PdfReader reader = new PdfReader(inputStream);

    PdfStamper stp = PdfStamper.createSignature(reader, outputStream, '\0', null, true);

    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    sap.setCrypto(null, getCertificateChain(), null, PdfSignatureAppearance.WINCER_SIGNED);
    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
    dic.setReason(siginfo.getSignatureReason());
    dic.setLocation(siginfo.getSignatureLocation());
    dic.setName(siginfo.getSignatureName());
    dic.setDate(new PdfDate(sap.getSignDate()));
    sap.setCryptoDictionary(dic);

    // get the selected rectangle and pagenumber for visible signature
    Rectangle signatureRect = new Rectangle(siginfo.getSignatureRect().left, siginfo.getSignatureRect().bottom,
            siginfo.getSignatureRect().right, siginfo.getSignatureRect().top);
    int pageNumber = siginfo.getPageNumber();
    sap.setVisibleSignature(signatureRect, pageNumber, null);

    // set signature picture, if there is one
    if (siginfo.getSignatureType() == SignatureType.PICTURE) {
        Image obj_pic = Image.getInstance(siginfo.getImagePath());
        sap.setImage(obj_pic);
    }

    // preserve some space for the contents
    HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
    exc.put(PdfName.CONTENTS, new Integer(SIGNATURE_MAX_SIZE * 2 + 2));
    sap.preClose(exc);

    // Save placeholder which will be replaced with actual signature later
    byte[] placeHolder = getPlaceHolderArr(SIGNATURE_MAX_SIZE * 2);
    // Replace the contents
    PdfDictionary dic2 = new PdfDictionary();
    dic2.put(PdfName.CONTENTS, new PdfString(placeHolder).setHexWriting(true));
    sap.close(dic2);

    // Calculate the digest
    InputStream data = sap.getRangeStream();

    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    byte buf[] = new byte[8192];
    int n;
    while ((n = data.read(buf)) > 0) {
        messageDigest.update(buf, 0, n);
    }

    hash = messageDigest.digest();

    calendar = Calendar.getInstance();
    ocsp = ocspRequest(cert, issuerCert);
    System.out.println("Got OCSP response, length = " + ocsp.length);

    // Calculate another digest over authenticatedAttributes
    PdfPKCS7 sgn = new PdfPKCS7(null, getCertificateChain(), null, hashAlgo, null, true);
    byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, calendar, ocsp);

    return sh;
}

From source file:androidGLUESigner.pdf.PDFSignerEngine.java

License:Open Source License

/**
 * Simple Sign method to create a signature without Online Timestamp (needed if device
 * has no internet connection)/*from ww w.j a  v  a  2s.co  m*/
 * 
 * @param inputfile the inputfile
 * @param outputfile the outpuftile
 * @param connection the IConnection Object
 */
public void simpleSign(String inputfile, String outputfile, IConnection connection)
        throws IOException, DocumentException, CertificateException, InvalidKeyException,
        NoSuchAlgorithmException, SignatureException, ReaderException {
    try {
        SignatureInfo sigInfo = getSiginfo();
        PdfReader reader = new PdfReader(inputfile);
        FileOutputStream fout = new FileOutputStream(outputfile);
        PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', null, true);
        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(null, new Certificate[] { getCertificateChain()[0] }, null,
                PdfSignatureAppearance.SELF_SIGNED);
        sap.setReason(sigInfo.getSignatureReason());
        sap.setLocation(sigInfo.getSignatureLocation());

        // get the selected rectangle and pagenumber for visible signature
        Rectangle signatureRect = new Rectangle(siginfo.getSignatureRect().left,
                siginfo.getSignatureRect().bottom, siginfo.getSignatureRect().right,
                siginfo.getSignatureRect().top);
        int pageNumber = siginfo.getPageNumber();
        sap.setVisibleSignature(signatureRect, pageNumber, null);
        // set signature picture, if there is one
        if (siginfo.getSignatureType() == SignatureType.PICTURE) {
            Image obj_pic = Image.getInstance(siginfo.getImagePath());
            sap.setImage(obj_pic);
        }

        sap.setExternalDigest(new byte[256], new byte[20], null);
        sap.preClose();

        java.io.InputStream inp = sap.getRangeStream();
        byte bytesToHash[] = IOUtils.toByteArray(inp);

        // sign the hash value
        byte[] signed = connection.sign(bytesToHash);

        PdfPKCS7 pdfSignature = sap.getSigStandard().getSigner();
        pdfSignature.setExternalDigest(signed, null, "RSA");

        PdfDictionary dic = new PdfDictionary();
        dic.put(PdfName.CONTENTS, new PdfString(pdfSignature.getEncodedPKCS1()).setHexWriting(true));
        sap.close(dic);
    } catch (Exception e) {
        Logger.toConsole(e);
    }
}

From source file:com.orange.atk.atkUI.corecli.utils.PdfUtilities.java

License:Apache License

private void signDocument(String pdfFileName) {
    try {/*from w  w  w .  j ava2  s.com*/
        // 1. copy
        File tmpPDFFile = new File(tmpDir, "tmp2PDF.pdf");
        copyFile(new File(pdfFileName), tmpPDFFile);
        // 2. sign
        KeyStore ks = KeyStore.getInstance(typeKeystore);
        FileInputStream fis = new FileInputStream(keystore);
        ks.load(fis, passwordKeystore.toCharArray());
        PrivateKey key = (PrivateKey) ks.getKey(aliasCertificate, passwordKeystore.toCharArray());
        Certificate[] chain = ks.getCertificateChain(aliasCertificate);
        PdfReader reader = new PdfReader(tmpPDFFile.getAbsolutePath());
        FileOutputStream fout = new FileOutputStream(pdfFileName);
        PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
        sap.setVisibleSignature(new Rectangle(450, 730, 550, 780), 1, null);
        stp.close();
        fis.close();
    } catch (Exception e) {
        e.printStackTrace(Out.log);
    }
}

From source file:ec.gov.informatica.firmadigital.FirmaDigital.java

License:Open Source License

/**
 * Firma un archivo./*from   w  ww  .j  av  a 2  s. co m*/
 * 
 * @param data
 * @return
 */
//   public void firmar(String claveToken,
//         String tipoCertificado, String urlCertificado, String path) {
public void firmar(String claveToken, String tipoCertificado, String path) {
    try {
        KeyStore keyStore = null;
        Enumeration<String> enumeration = null;
        String alias = null;
        PrivateKey privateKey = null;
        Certificate[] certs = null;
        CMSSignatureProcessor cms = null;
        KeyStoreProvider keyStoreProvider = null;
        try {
            if (tipoCertificado.equals("1") || tipoCertificado.equals("2") || tipoCertificado.equals("3")) {
                System.out.println("- Firmando con certificado token." + tipoCertificado);
                keyStoreProvider = this.getKeyStoreProvider(tipoCertificado);
                System.out.println(claveToken.toCharArray());
                keyStore = keyStoreProvider.getKeystore(claveToken.toCharArray());
                enumeration = keyStore.aliases();
                alias = enumeration.nextElement();
                privateKey = (PrivateKey) keyStore.getKey(alias, null);
                cms = new BouncyCastleSignatureProcessor(keyStore);
            }
            // if (tipoCertificado.equals("4")) {
            // System.out.println("- Firmando con certificado en archivo.");
            // keyStore = java.security.KeyStore.getInstance("PKCS12"); //
            // instancia el ks
            // keyStore.load(new java.io.FileInputStream(urlCertificado),
            // claveToken.toCharArray());
            // Enumeration en = keyStore.aliases();
            // alias = "";
            // Vector vectaliases = new Vector();
            // while (en.hasMoreElements()) {
            // vectaliases.add(en.nextElement());
            // }
            // String[] aliases = (String[]) (vectaliases.toArray(new
            // String[0]));
            // for (int i = 0; i < aliases.length; i++) {
            // if (keyStore.isKeyEntry(aliases[i])) {
            // alias = aliases[i];
            // break;
            // }
            // }
            // privateKey = (PrivateKey) keyStore.getKey(alias,
            // claveToken.toCharArray());
            // cms = new BouncyCastleSignatureProcessor(keyStore);
            // }
        } catch (Exception e) {
            System.out.println(" \n Fallo trayendo keystore " + e.getMessage());
        }
        certs = keyStore.getCertificateChain(alias);
        Certificate[] chain = keyStore.getCertificateChain(alias);
        PrivateKey key = (PrivateKey) keyStore.getKey(alias, claveToken.toCharArray());
        String revocados = ""; // para verificar revocados
        revocados = verificaRevocados(((X509Certificate) certs[0]).getSerialNumber().toString(),
                tipoCertificado);
        if (!revocados.isEmpty()) {
            System.out.println(" CERTIFICADO REVOCADO " + revocados);
            return;
        }
        System.out.println("- Certificado valido ");

        PdfReader reader = new PdfReader(path);
        FileOutputStream fout = new FileOutputStream(path + ".Firmado.pdf");
        PdfStamper stp = PdfStamper.createSignature(reader, fout, '?');
        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
        sap.setReason("Firma Procesos Legales");
        sap.setLocation("RedTools");
        // Aade la firma visible. Podemos comentarla para que no sea
        // visible.
        sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
        stp.close();

        //         byte[] datosFirmados = cms.sign(data, privateKey, certs);
        System.out.println("Firmado Correctamente..!");
        //         this.datosUsuarioActual = this
        //               .crearDatosUsuario((X509Certificate) certs[0]); // llena la
        // clase de
        // tipo
        // datosUsuario
        // con el
        // certificado
        // actual

        //         return datosFirmados;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e); // FIXME
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        throw new RuntimeException(e);
    } catch (DocumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        throw new RuntimeException(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 {/*  w  w  w .  j  a v  a  2  s.  co 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:es.gob.afirma.signers.pades.PdfSessionManager.java

License:Open Source License

/** Obtiene los datos PDF relevantes en cuanto a las firmas electr&oacute;nicas, consistentes en los datos
 * a ser firmados con CAdES o PKCS#7 y los metadatos necesarios para su correcta inserci&oacute;n en el PDF.
 * @param inPDF Documento PDF que se desea firmar
 * @param certChain Cadena de certificados del firmante
 * @param signTime Hora de la firma//from ww  w  . j  a v a 2 s .  c om
 * @param extraParams Par&aacute;metros adicionales de la firma
 * @return Datos PDF relevantes en cuanto a las firmas electr&oacute;nicas
 * @throws AOException En caso de que ocurra cualquier otro tipo de error
 * @throws IOException En caso de errores de entrada / salida
 * @throws DocumentException Si ocurren errores en la estampaci&iacute;n de la firma PDF */
public static PdfTriPhaseSession getSessionData(final byte[] inPDF, final Certificate[] certChain,
        final Calendar signTime, final Properties extraParams)
        throws AOException, IOException, DocumentException {

    // *********************************************************************************************************************
    // **************** LECTURA PARAMETROS ADICIONALES *********************************************************************
    // *********************************************************************************************************************

    // Forzar la creacion de revisiones incluso en PDF no firmados
    final boolean alwaysCreateRevision = Boolean
            .parseBoolean(extraParams.getProperty("alwaysCreateRevision", "true")); //$NON-NLS-1$ //$NON-NLS-2$

    // Imagen de la rubrica
    final Image rubric = PdfPreProcessor.getImage(extraParams.getProperty("signatureRubricImage")); //$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 {
        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$

    // 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 **
    // *****************************

    // *********************************************************************************************************************
    // **************** FIN LECTURA PARAMETROS ADICIONALES *****************************************************************
    // *********************************************************************************************************************

    final PdfReader pdfReader = PdfUtil.getPdfReader(inPDF, extraParams,
            Boolean.getBoolean(extraParams.getProperty("headLess")) //$NON-NLS-1$
    );

    //PdfUtil.checkPdfCertification(pdfReader.getCertificationLevel(), extraParams);
    //PdfUtil.checkUnregisteredSignatures(pdfReader, extraParams);

    // 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" (quinto 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 procedimiento no funciona cuando los PDF contienen informacion
    // despues de la ultima marca %%EOF, aspecto no permitido en PDF 1.7 (ISO 32000-1:2008)
    // pero si en PDF 1.3 (Adobe) y que se da con frecuencia en PDF generados con bibliotetcas
    // de software libre como QPDF.
    //
    //  Especificacion PDF 1.3
    //   3.4.4, "File Trailer"
    //     Acrobat viewers require only that the %%EOF marker appear somewhere within
    //     the last 1024 bytes of the file.
    //
    //  Especificacion PDF 1.7
    //   7.5.5. File Trailer
    //     The trailer of a PDF file enables a conforming reader to quickly find the
    //     cross-reference table and certain special objects. Conforming readers should read a
    //     PDF file from its end. The last line of the file shall contain only the end-of-file
    //     marker, %%EOF.
    //
    // Para aceptar al menos en algunos casos PDF 1.3 (son aun muy frecuentes, especialmente
    // en archivos, lo mantendremos desactivado para la primera firma y activado para las
    // subsiguientes.
    //
    // No obstante, el integrador puede siempre forzar la creacion de revisiones mediante
    // el parametro "alwaysCreateRevision".
    final PdfStamper stp;
    try {
        stp = PdfStamper.createSignature(
                // PDF de entrada
                pdfReader,
                // Salida
                baos,
                // Mantener version
                '\0',
                // No crear temporal
                null,
                // Si hay mas firmas o asi me lo indican, creo una revision
                alwaysCreateRevision || pdfReader.getAcroFields().getSignatureNames().size() > 0,
                // Momento de la firma
                signTime);
    } 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.getBoolean(extraParams.getProperty("headLess"))) { //$NON-NLS-1$
            throw new BadPdfPasswordException(e);
        }
        // La contrasena que nos han proporcionada no es buena o no nos
        // proporcionaron ninguna
        final String userPwd = new String(AOUIFactory.getPassword(
                extraParams.getProperty("userPassword") == null ? CommonPdfMessages.getString("AOPDFSigner.0") //$NON-NLS-1$//$NON-NLS-2$
                        : CommonPdfMessages.getString("AOPDFSigner.1"), //$NON-NLS-1$
                null));
        if ("".equals(userPwd)) { //$NON-NLS-1$
            throw new AOCancelledOperationException("Entrada de contrasena de PDF cancelada por el usuario", e //$NON-NLS-1$
            );
        }
        extraParams.put("userPassword", userPwd); //$NON-NLS-1$
        return getSessionData(inPDF, certChain, signTime, extraParams);
    }

    // Aplicamos todos los atributos de firma
    final PdfSignatureAppearance sap = stp.getSignatureAppearance();
    stp.setFullCompression();
    sap.setAcro6Layers(true);

    PdfUtil.enableLtv(stp);

    // Adjuntos
    PdfPreProcessor.attachFile(extraParams, stp);

    // Imagenes
    PdfPreProcessor.addImage(extraParams, stp);

    // Establecemos el render segun iText antiguo, varia en versiones modernas
    sap.setRender(PdfSignatureAppearance.SignatureRenderDescription);

    // Razon de firma
    if (reason != null) {
        sap.setReason(reason);
    }

    sap.setSignDate(signTime);

    // Gestion de los cifrados
    PdfUtil.managePdfEncryption(stp, pdfReader, extraParams);

    // 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(Integer.valueOf(layer2FontColorR), Integer.valueOf(layer2FontColorG),
                            Integer.valueOf(layer2FontColorB));

            font = com.lowagie.text.Font.class
                    .getConstructor(Integer.TYPE, Float.TYPE, Integer.TYPE, colorClass).newInstance(
                            // Family (COURIER = 0, HELVETICA = 1, TIMES_ROMAN = 2, SYMBOL = 3, ZAPFDINGBATS = 4)
                            Integer.valueOf(layer2FontFamily == UNDEFINED ? COURIER : layer2FontFamily),
                            // Size (DEFAULTSIZE = 12)
                            Float.valueOf(
                                    layer2FontSize == UNDEFINED ? DEFAULT_LAYER_2_FONT_SIZE : layer2FontSize),
                            // Style (NORMAL = 0, BOLD = 1, ITALIC = 2, BOLDITALIC = 3, UNDERLINE = 4, STRIKETHRU = 8)
                            Integer.valueOf(layer2FontStyle == UNDEFINED ? com.lowagie.text.Font.NORMAL
                                    : layer2FontStyle),
                            // Color
                            color);
        } catch (final 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, signTime);

    final PdfObject pdfObject = ((com.lowagie.text.pdf.PdfStamperImp) stp.getWriter()).getFileID();

    return new PdfTriPhaseSession(sap, baos, new String(pdfObject.getBytes()));
}

From source file:net.sf.jsignpdf.SignerLogic.java

License:Mozilla Public License

/**
 * Signs a single file.// ww w  .jav a2 s  .  c om
 * 
 * @return true when signing is finished succesfully, false otherwise
 */
public boolean signFile() {
    final String outFile = options.getOutFileX();
    if (!validateInOutFiles(options.getInFile(), outFile)) {
        LOGGER.info(RES.get("console.skippingSigning"));
        return false;
    }

    boolean finished = false;
    Throwable tmpException = null;
    FileOutputStream fout = null;
    try {
        SSLInitializer.init(options);

        final PrivateKeyInfo pkInfo = KeyStoreUtils.getPkInfo(options);
        final PrivateKey key = pkInfo.getKey();
        final Certificate[] chain = pkInfo.getChain();
        if (ArrayUtils.isEmpty(chain)) {
            // the certificate was not found
            LOGGER.info(RES.get("console.certificateChainEmpty"));
            return false;
        }
        LOGGER.info(RES.get("console.createPdfReader", options.getInFile()));
        PdfReader reader;
        try {
            reader = new PdfReader(options.getInFile(), options.getPdfOwnerPwdStrX().getBytes());
        } catch (Exception e) {
            try {
                reader = new PdfReader(options.getInFile(), new byte[0]);
            } catch (Exception e2) {
                // try to read without password
                reader = new PdfReader(options.getInFile());
            }
        }

        LOGGER.info(RES.get("console.createOutPdf", outFile));
        fout = new FileOutputStream(outFile);

        final HashAlgorithm hashAlgorithm = options.getHashAlgorithmX();

        LOGGER.info(RES.get("console.createSignature"));
        char tmpPdfVersion = '\0'; // default version - the same as input
        if (reader.getPdfVersion() < hashAlgorithm.getPdfVersion()) {
            // this covers also problems with visible signatures (embedded
            // fonts) in PDF 1.2, because the minimal version
            // for hash algorithms is 1.3 (for SHA1)
            if (options.isAppendX()) {
                // if we are in append mode and version should be updated
                // then return false (not possible)
                LOGGER.info(RES.get("console.updateVersionNotPossibleInAppendMode"));
                return false;
            }
            tmpPdfVersion = hashAlgorithm.getPdfVersion();
            LOGGER.info(RES.get("console.updateVersion",
                    new String[] { String.valueOf(reader.getPdfVersion()), String.valueOf(tmpPdfVersion) }));
        }

        final PdfStamper stp = PdfStamper.createSignature(reader, fout, tmpPdfVersion, null,
                options.isAppendX());
        if (!options.isAppendX()) {
            // we are not in append mode, let's remove existing signatures
            // (otherwise we're getting to troubles)
            final AcroFields acroFields = stp.getAcroFields();
            @SuppressWarnings("unchecked")
            final List<String> sigNames = acroFields.getSignatureNames();
            for (String sigName : sigNames) {
                acroFields.removeField(sigName);
            }
        }
        if (options.isAdvanced() && options.getPdfEncryption() != PDFEncryption.NONE) {
            LOGGER.info(RES.get("console.setEncryption"));
            final int tmpRight = options.getRightPrinting().getRight()
                    | (options.isRightCopy() ? PdfWriter.ALLOW_COPY : 0)
                    | (options.isRightAssembly() ? PdfWriter.ALLOW_ASSEMBLY : 0)
                    | (options.isRightFillIn() ? PdfWriter.ALLOW_FILL_IN : 0)
                    | (options.isRightScreanReaders() ? PdfWriter.ALLOW_SCREENREADERS : 0)
                    | (options.isRightModifyAnnotations() ? PdfWriter.ALLOW_MODIFY_ANNOTATIONS : 0)
                    | (options.isRightModifyContents() ? PdfWriter.ALLOW_MODIFY_CONTENTS : 0);
            switch (options.getPdfEncryption()) {
            case PASSWORD:
                stp.setEncryption(true, options.getPdfUserPwdStr(), options.getPdfOwnerPwdStrX(), tmpRight);
                break;
            case CERTIFICATE:
                final X509Certificate encCert = KeyStoreUtils
                        .loadCertificate(options.getPdfEncryptionCertFile());
                if (encCert == null) {
                    LOGGER.error(RES.get("console.pdfEncError.wrongCertificateFile",
                            StringUtils.defaultString(options.getPdfEncryptionCertFile())));
                    return false;
                }
                if (!KeyStoreUtils.isEncryptionSupported(encCert)) {
                    LOGGER.error(RES.get("console.pdfEncError.cantUseCertificate",
                            encCert.getSubjectDN().getName()));
                    return false;
                }
                stp.setEncryption(new Certificate[] { encCert }, new int[] { tmpRight },
                        PdfWriter.ENCRYPTION_AES_128);
                break;
            default:
                LOGGER.error(RES.get("console.unsupportedEncryptionType"));
                return false;
            }
        }

        final PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
        final String reason = options.getReason();
        if (StringUtils.isNotEmpty(reason)) {
            LOGGER.info(RES.get("console.setReason", reason));
            sap.setReason(reason);
        }
        final String location = options.getLocation();
        if (StringUtils.isNotEmpty(location)) {
            LOGGER.info(RES.get("console.setLocation", location));
            sap.setLocation(location);
        }
        final String contact = options.getContact();
        if (StringUtils.isNotEmpty(contact)) {
            LOGGER.info(RES.get("console.setContact", contact));
            sap.setContact(contact);
        }
        LOGGER.info(RES.get("console.setCertificationLevel"));
        sap.setCertificationLevel(options.getCertLevelX().getLevel());

        if (options.isVisible()) {
            // visible signature is enabled
            LOGGER.info(RES.get("console.configureVisible"));
            LOGGER.info(RES.get("console.setAcro6Layers", Boolean.toString(options.isAcro6Layers())));
            sap.setAcro6Layers(options.isAcro6Layers());

            final String tmpImgPath = options.getImgPath();
            if (tmpImgPath != null) {
                LOGGER.info(RES.get("console.createImage", tmpImgPath));
                final Image img = Image.getInstance(tmpImgPath);
                LOGGER.info(RES.get("console.setSignatureGraphic"));
                sap.setSignatureGraphic(img);
            }
            final String tmpBgImgPath = options.getBgImgPath();
            if (tmpBgImgPath != null) {
                LOGGER.info(RES.get("console.createImage", tmpBgImgPath));
                final Image img = Image.getInstance(tmpBgImgPath);
                LOGGER.info(RES.get("console.setImage"));
                sap.setImage(img);
            }
            LOGGER.info(RES.get("console.setImageScale"));
            sap.setImageScale(options.getBgImgScale());
            LOGGER.info(RES.get("console.setL2Text"));
            final String signer = PdfPKCS7.getSubjectFields((X509Certificate) chain[0]).getField("CN");
            final String timestamp = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z")
                    .format(sap.getSignDate().getTime());
            if (options.getL2Text() != null) {
                final Map<String, String> replacements = new HashMap<String, String>();
                replacements.put(L2TEXT_PLACEHOLDER_SIGNER, StringUtils.defaultString(signer));
                replacements.put(L2TEXT_PLACEHOLDER_TIMESTAMP, timestamp);
                replacements.put(L2TEXT_PLACEHOLDER_LOCATION, StringUtils.defaultString(location));
                replacements.put(L2TEXT_PLACEHOLDER_REASON, StringUtils.defaultString(reason));
                replacements.put(L2TEXT_PLACEHOLDER_CONTACT, StringUtils.defaultString(contact));
                final String l2text = StrSubstitutor.replace(options.getL2Text(), replacements);
                sap.setLayer2Text(l2text);
            } else {
                final StringBuilder buf = new StringBuilder();
                buf.append(RES.get("default.l2text.signedBy")).append(" ").append(signer).append('\n');
                buf.append(RES.get("default.l2text.date")).append(" ").append(timestamp);
                if (StringUtils.isNotEmpty(reason))
                    buf.append('\n').append(RES.get("default.l2text.reason")).append(" ").append(reason);
                if (StringUtils.isNotEmpty(location))
                    buf.append('\n').append(RES.get("default.l2text.location")).append(" ").append(location);
                sap.setLayer2Text(buf.toString());
            }
            if (FontUtils.getL2BaseFont() != null) {
                sap.setLayer2Font(new Font(FontUtils.getL2BaseFont(), options.getL2TextFontSize()));
            }
            LOGGER.info(RES.get("console.setL4Text"));
            sap.setLayer4Text(options.getL4Text());
            LOGGER.info(RES.get("console.setRender"));
            RenderMode renderMode = options.getRenderMode();
            if (renderMode == RenderMode.GRAPHIC_AND_DESCRIPTION && sap.getSignatureGraphic() == null) {
                LOGGER.warn(
                        "Render mode of visible signature is set to GRAPHIC_AND_DESCRIPTION, but no image is loaded. Fallback to DESCRIPTION_ONLY.");
                LOGGER.info(RES.get("console.renderModeFallback"));
                renderMode = RenderMode.DESCRIPTION_ONLY;
            }
            sap.setRender(renderMode.getRender());
            LOGGER.info(RES.get("console.setVisibleSignature"));
            int page = options.getPage();
            if (page < 1 || page > reader.getNumberOfPages()) {
                page = reader.getNumberOfPages();
            }
            sap.setVisibleSignature(new Rectangle(options.getPositionLLX(), options.getPositionLLY(),
                    options.getPositionURX(), options.getPositionURY()), page, null);
        }

        LOGGER.info(RES.get("console.processing"));
        final PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
        if (!StringUtils.isEmpty(reason)) {
            dic.setReason(sap.getReason());
        }
        if (!StringUtils.isEmpty(location)) {
            dic.setLocation(sap.getLocation());
        }
        if (!StringUtils.isEmpty(contact)) {
            dic.setContact(sap.getContact());
        }
        dic.setDate(new PdfDate(sap.getSignDate()));
        sap.setCryptoDictionary(dic);

        final Proxy tmpProxy = options.createProxy();

        final CRLInfo crlInfo = new CRLInfo(options, chain);

        // CRLs are stored twice in PDF c.f.
        // PdfPKCS7.getAuthenticatedAttributeBytes
        final int contentEstimated = (int) (Constants.DEFVAL_SIG_SIZE + 2L * crlInfo.getByteCount());
        final Map<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
        exc.put(PdfName.CONTENTS, new Integer(contentEstimated * 2 + 2));
        sap.preClose(exc);

        PdfPKCS7 sgn = new PdfPKCS7(key, chain, crlInfo.getCrls(), hashAlgorithm.getAlgorithmName(), null,
                false);
        InputStream data = sap.getRangeStream();
        final MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm.getAlgorithmName());
        byte buf[] = new byte[8192];
        int n;
        while ((n = data.read(buf)) > 0) {
            messageDigest.update(buf, 0, n);
        }
        byte hash[] = messageDigest.digest();
        Calendar cal = Calendar.getInstance();
        byte[] ocsp = null;
        if (options.isOcspEnabledX() && chain.length >= 2) {
            LOGGER.info(RES.get("console.getOCSPURL"));
            String url = PdfPKCS7.getOCSPURL((X509Certificate) chain[0]);
            if (StringUtils.isEmpty(url)) {
                // get from options
                LOGGER.info(RES.get("console.noOCSPURL"));
                url = options.getOcspServerUrl();
            }
            if (!StringUtils.isEmpty(url)) {
                LOGGER.info(RES.get("console.readingOCSP", url));
                final OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle((X509Certificate) chain[0],
                        (X509Certificate) chain[1], url);
                ocspClient.setProxy(tmpProxy);
                ocsp = ocspClient.getEncoded();
            }
        }
        byte sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, ocsp);
        sgn.update(sh, 0, sh.length);

        TSAClientBouncyCastle tsc = null;
        if (options.isTimestampX() && !StringUtils.isEmpty(options.getTsaUrl())) {
            LOGGER.info(RES.get("console.creatingTsaClient"));
            if (options.getTsaServerAuthn() == ServerAuthentication.PASSWORD) {
                tsc = new TSAClientBouncyCastle(options.getTsaUrl(),
                        StringUtils.defaultString(options.getTsaUser()),
                        StringUtils.defaultString(options.getTsaPasswd()));
            } else {
                tsc = new TSAClientBouncyCastle(options.getTsaUrl());

            }
            final String tsaHashAlg = options.getTsaHashAlgWithFallback();
            LOGGER.info(RES.get("console.settingTsaHashAlg", tsaHashAlg));
            tsc.setHashAlgorithm(tsaHashAlg);
            tsc.setProxy(tmpProxy);
            final String policyOid = options.getTsaPolicy();
            if (StringUtils.isNotEmpty(policyOid)) {
                LOGGER.info(RES.get("console.settingTsaPolicy", policyOid));
                tsc.setPolicy(policyOid);
            }
        }
        byte[] encodedSig = sgn.getEncodedPKCS7(hash, cal, tsc, ocsp);

        if (contentEstimated + 2 < encodedSig.length) {
            System.err.println(
                    "SigSize - contentEstimated=" + contentEstimated + ", sigLen=" + encodedSig.length);
            throw new Exception("Not enough space");
        }

        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));
        LOGGER.info(RES.get("console.closeStream"));
        sap.close(dic2);
        fout.close();
        fout = null;
        finished = true;
    } catch (Exception e) {
        LOGGER.error(RES.get("console.exception"), e);
    } catch (OutOfMemoryError e) {
        LOGGER.fatal(RES.get("console.memoryError"), e);
    } finally {
        if (fout != null) {
            try {
                fout.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        LOGGER.info(RES.get("console.finished." + (finished ? "ok" : "error")));
        options.fireSignerFinishedEvent(tmpException);
    }
    return finished;
}

From source file:org.allcolor.yahp.cl.converter.CDocumentReconstructor.java

License:Open Source License

/**
 * construct a pdf document from pdf parts.
 * //www.java2s  .  c  om
 * @param files
 *            list containing the pdf to assemble
 * @param properties
 *            converter properties
 * @param fout
 *            outputstream to write the new pdf
 * @param base_url
 *            base url of the document
 * @param producer
 *            producer of the pdf
 * 
 * @throws CConvertException
 *             if an error occured while reconstruct.
 */
public static void reconstruct(final List files, final Map properties, final OutputStream fout,
        final String base_url, final String producer, final PageSize[] size, final List hf)
        throws CConvertException {
    OutputStream out = fout;
    OutputStream out2 = fout;
    boolean signed = false;
    OutputStream oldOut = null;
    File tmp = null;
    File tmp2 = null;
    try {
        tmp = File.createTempFile("yahp", "pdf");
        tmp2 = File.createTempFile("yahp", "pdf");
        oldOut = out;
        if ("true".equals(properties.get(IHtmlToPdfTransformer.USE_PDF_SIGNING))) {
            signed = true;
            out2 = new FileOutputStream(tmp2);
        } // end if
        else {
            out2 = oldOut;
        }
        out = new FileOutputStream(tmp);
        com.lowagie.text.Document document = null;
        PdfCopy writer = null;
        boolean first = true;

        Map mapSizeDoc = new HashMap();

        int totalPage = 0;

        for (int i = 0; i < files.size(); i++) {
            final File fPDF = (File) files.get(i);
            final PdfReader reader = new PdfReader(fPDF.getAbsolutePath());
            reader.consolidateNamedDestinations();

            final int n = reader.getNumberOfPages();

            if (first) {
                first = false;
                // step 1: creation of a document-object
                // set title/creator/author
                document = new com.lowagie.text.Document(reader.getPageSizeWithRotation(1));
                // step 2: we create a writer that listens to the document
                writer = new PdfCopy(document, out);
                // use pdf version 1.5
                writer.setPdfVersion(PdfWriter.VERSION_1_3);
                // compress the pdf
                writer.setFullCompression();

                // check if encryption is needed
                if ("true".equals(properties.get(IHtmlToPdfTransformer.USE_PDF_ENCRYPTION))) {
                    final String password = (String) properties
                            .get(IHtmlToPdfTransformer.PDF_ENCRYPTION_PASSWORD);
                    final int securityType = CDocumentReconstructor.getSecurityFlags(properties);
                    writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, password, null, securityType);
                } // end if

                final String title = (String) properties.get(IHtmlToPdfTransformer.PDF_TITLE);

                if (title != null) {
                    document.addTitle(title);
                } // end if
                else if (base_url != null) {
                    document.addTitle(base_url);
                } // end else if

                final String creator = (String) properties.get(IHtmlToPdfTransformer.PDF_CREATOR);

                if (creator != null) {
                    document.addCreator(creator);
                } // end if
                else {
                    document.addCreator(IHtmlToPdfTransformer.VERSION);
                } // end else

                final String author = (String) properties.get(IHtmlToPdfTransformer.PDF_AUTHOR);

                if (author != null) {
                    document.addAuthor(author);
                } // end if

                final String sproducer = (String) properties.get(IHtmlToPdfTransformer.PDF_PRODUCER);

                if (sproducer != null) {
                    document.add(new Meta("Producer", sproducer));
                } // end if
                else {
                    document.add(new Meta("Producer", (IHtmlToPdfTransformer.VERSION
                            + " - http://www.allcolor.org/YaHPConverter/ - " + producer)));
                } // end else

                // step 3: we open the document
                document.open();
            } // end if

            PdfImportedPage page;

            for (int j = 0; j < n;) {
                ++j;
                totalPage++;
                mapSizeDoc.put("" + totalPage, "" + i);
                page = writer.getImportedPage(reader, j);
                writer.addPage(page);
            } // end for
        } // end for

        document.close();
        out.flush();
        out.close();
        {
            final PdfReader reader = new PdfReader(tmp.getAbsolutePath());
            ;
            final int n = reader.getNumberOfPages();
            final PdfStamper stp = new PdfStamper(reader, out2);
            int i = 0;
            BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
            final CHtmlToPdfFlyingSaucerTransformer trans = new CHtmlToPdfFlyingSaucerTransformer();
            while (i < n) {
                i++;
                int indexSize = Integer.parseInt((String) mapSizeDoc.get("" + i));
                final int[] dsize = size[indexSize].getSize();
                final int[] dmargin = size[indexSize].getMargin();
                for (final Iterator it = hf.iterator(); it.hasNext();) {
                    final CHeaderFooter chf = (CHeaderFooter) it.next();
                    if (chf.getSfor().equals(CHeaderFooter.ODD_PAGES) && (i % 2 == 0)) {
                        continue;
                    } else if (chf.getSfor().equals(CHeaderFooter.EVEN_PAGES) && (i % 2 != 0)) {
                        continue;
                    }
                    final String text = chf.getContent().replaceAll("<pagenumber>", "" + i)
                            .replaceAll("<pagecount>", "" + n);
                    // text over the existing page
                    final PdfContentByte over = stp.getOverContent(i);
                    final ByteArrayOutputStream bbout = new ByteArrayOutputStream();
                    if (chf.getType().equals(CHeaderFooter.HEADER)) {
                        trans.transform(new ByteArrayInputStream(text.getBytes("utf-8")), base_url,
                                new PageSize(dsize[0] - (dmargin[0] + dmargin[1]), dmargin[3]), new ArrayList(),
                                properties, bbout);
                    } else if (chf.getType().equals(CHeaderFooter.FOOTER)) {
                        trans.transform(new ByteArrayInputStream(text.getBytes("utf-8")), base_url,
                                new PageSize(dsize[0] - (dmargin[0] + dmargin[1]), dmargin[2]), new ArrayList(),
                                properties, bbout);
                    }
                    final PdfReader readerHF = new PdfReader(bbout.toByteArray());
                    if (chf.getType().equals(CHeaderFooter.HEADER)) {
                        over.addTemplate(stp.getImportedPage(readerHF, 1), dmargin[0], dsize[1] - dmargin[3]);
                    } else if (chf.getType().equals(CHeaderFooter.FOOTER)) {
                        over.addTemplate(stp.getImportedPage(readerHF, 1), dmargin[0], 0);
                    }
                    readerHF.close();
                }
            }
            stp.close();
        }
        try {
            out2.flush();
        } catch (Exception ignore) {
        } finally {
            try {
                out2.close();
            } catch (Exception ignore) {
            }
        }
        if (signed) {

            final String keypassword = (String) properties
                    .get(IHtmlToPdfTransformer.PDF_SIGNING_PRIVATE_KEY_PASSWORD);
            final String password = (String) properties.get(IHtmlToPdfTransformer.PDF_ENCRYPTION_PASSWORD);
            final String keyStorepassword = (String) properties
                    .get(IHtmlToPdfTransformer.PDF_SIGNING_KEYSTORE_PASSWORD);
            final String privateKeyFile = (String) properties
                    .get(IHtmlToPdfTransformer.PDF_SIGNING_PRIVATE_KEY_FILE);
            final String reason = (String) properties.get(IHtmlToPdfTransformer.PDF_SIGNING_REASON);
            final String location = (String) properties.get(IHtmlToPdfTransformer.PDF_SIGNING_LOCATION);
            final boolean selfSigned = !"false"
                    .equals(properties.get(IHtmlToPdfTransformer.USE_PDF_SELF_SIGNING));
            PdfReader reader = null;

            if (password != null) {
                reader = new PdfReader(tmp2.getAbsolutePath(), password.getBytes());
            } // end if
            else {
                reader = new PdfReader(tmp2.getAbsolutePath());
            } // end else

            final KeyStore ks = selfSigned ? KeyStore.getInstance(KeyStore.getDefaultType())
                    : KeyStore.getInstance("pkcs12");
            ks.load(new FileInputStream(privateKeyFile), keyStorepassword.toCharArray());

            final String alias = (String) ks.aliases().nextElement();
            final PrivateKey key = (PrivateKey) ks.getKey(alias, keypassword.toCharArray());
            final Certificate chain[] = ks.getCertificateChain(alias);
            final PdfStamper stp = PdfStamper.createSignature(reader, oldOut, '\0');

            if ("true".equals(properties.get(IHtmlToPdfTransformer.USE_PDF_ENCRYPTION))) {
                stp.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, password, null,
                        CDocumentReconstructor.getSecurityFlags(properties));
            } // end if

            final PdfSignatureAppearance sap = stp.getSignatureAppearance();

            if (selfSigned) {
                sap.setCrypto(key, chain, null, PdfSignatureAppearance.SELF_SIGNED);
            } // end if
            else {
                sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
            } // end else

            if (reason != null) {
                sap.setReason(reason);
            } // end if

            if (location != null) {
                sap.setLocation(location);
            } // end if

            stp.close();
            oldOut.flush();
        } // end if
    } // end try
    catch (final Exception e) {
        throw new CConvertException(
                "ERROR: An Exception occured while reconstructing the pdf document: " + e.getMessage(), e);
    } // end catch
    finally {
        try {
            tmp.delete();
        } // end try
        catch (final Exception ignore) {
        }
        try {
            tmp2.delete();
        } // end try
        catch (final Exception ignore) {
        }
    } // end finally
}

From source file:org.nuxeo.ecm.platform.signature.core.sign.SignatureServiceImpl.java

License:Open Source License

@Override
public Blob signPDF(Blob pdfBlob, DocumentModel user, String keyPassword, String reason)
        throws ClientException {
    CertService certService = Framework.getLocalService(CertService.class);
    CUserService cUserService = Framework.getLocalService(CUserService.class);
    try {//from  w w w  . j  a  va2 s  . c om
        File outputFile = File.createTempFile("signed-", ".pdf");
        Blob blob = Blobs.createBlob(outputFile, MIME_TYPE_PDF);
        Framework.trackFile(outputFile, blob);

        PdfReader pdfReader = new PdfReader(pdfBlob.getStream());
        List<X509Certificate> pdfCertificates = getCertificates(pdfReader);

        // allows for multiple signatures
        PdfStamper pdfStamper = PdfStamper.createSignature(pdfReader, new FileOutputStream(outputFile), '\0',
                null, true);

        PdfSignatureAppearance pdfSignatureAppearance = pdfStamper.getSignatureAppearance();
        String userID = (String) user.getPropertyValue("user:username");
        AliasWrapper alias = new AliasWrapper(userID);
        KeyStore keystore = cUserService.getUserKeystore(userID, keyPassword);
        Certificate certificate = certService.getCertificate(keystore, alias.getId(AliasType.CERT));
        KeyPair keyPair = certService.getKeyPair(keystore, alias.getId(AliasType.KEY),
                alias.getId(AliasType.CERT), keyPassword);

        if (certificatePresentInPDF(certificate, pdfCertificates)) {
            X509Certificate userX509Certificate = (X509Certificate) certificate;
            String message = ALREADY_SIGNED_BY + userX509Certificate.getSubjectDN();
            log.debug(message);
            throw new AlreadySignedException(message);
        }

        List<Certificate> certificates = new ArrayList<Certificate>();
        certificates.add(certificate);

        Certificate[] certChain = certificates.toArray(new Certificate[0]);
        pdfSignatureAppearance.setCrypto(keyPair.getPrivate(), certChain, null,
                PdfSignatureAppearance.SELF_SIGNED);
        if (StringUtils.isBlank(reason)) {
            reason = getSigningReason();
        }
        pdfSignatureAppearance.setReason(reason);
        pdfSignatureAppearance.setAcro6Layers(true);
        Font layer2Font = FontFactory.getFont(FontFactory.TIMES, getSignatureLayout().getTextSize(),
                Font.NORMAL, new Color(0x00, 0x00, 0x00));
        pdfSignatureAppearance.setLayer2Font(layer2Font);
        pdfSignatureAppearance.setRender(PdfSignatureAppearance.SignatureRenderDescription);

        pdfSignatureAppearance.setVisibleSignature(getNextCertificatePosition(pdfReader, pdfCertificates), 1,
                null);

        pdfStamper.close(); // closes the file

        log.debug("File " + outputFile.getAbsolutePath() + " created and signed with " + reason);

        return blob;
    } catch (IOException e) {
        throw new SignException(e);
    } catch (DocumentException e) {
        // iText PDF stamping
        throw new SignException(e);
    } catch (IllegalArgumentException e) {
        if (String.valueOf(e.getMessage()).contains("PdfReader not opened with owner password")) {
            // iText PDF reading
            throw new SignException("PDF is password-protected");
        }
        throw new SignException(e);
    }
}

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.");
    }/* w  ww  . j  a  v a 2s .c  o 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();
}