Example usage for com.lowagie.text.pdf PdfName ADOBE_PPKLITE

List of usage examples for com.lowagie.text.pdf PdfName ADOBE_PPKLITE

Introduction

In this page you can find the example usage for com.lowagie.text.pdf PdfName ADOBE_PPKLITE.

Prototype

PdfName ADOBE_PPKLITE

To view the source code for com.lowagie.text.pdf PdfName ADOBE_PPKLITE.

Click Source Link

Document

A name

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/*from   w  w w. j a va 2 s. c  o m*/
 * @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: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  va  2s.c o  m*/
        page = Integer.parseInt(extraParams.getProperty("signaturePage")); //$NON-NLS-1$
    } catch (final Exception e) {
        /* Se deja la pagina tal y como esta */
    }

    // Nombre del subfiltro de firma en el diccionario PDF
    final String signatureSubFilter = extraParams.getProperty("signatureSubFilter"); //$NON-NLS-1$

    // ******************
    // ** Adjuntos ******

    // Contenido a adjuntar (en Base64)
    final String b64Attachment = extraParams.getProperty("attach"); //$NON-NLS-1$

    // Nombre que se pondra al fichero adjunto en el PDF
    final String attachmentFileName = extraParams.getProperty("attachFileName"); //$NON-NLS-1$

    // Descripcion del adjunto
    final String attachmentDescription = extraParams.getProperty("attachDescription"); //$NON-NLS-1$

    // ** Fin Adjuntos **
    // ******************

    // Nivel de certificacion del PDF
    int certificationLevel;
    try {
        certificationLevel = extraParams.getProperty("certificationLevel") != null ? //$NON-NLS-1$
                Integer.parseInt(extraParams.getProperty("certificationLevel")) : //$NON-NLS-1$
                -1;
    } catch (final Exception e) {
        certificationLevel = UNDEFINED;
    }

    // *****************************
    // **** Texto firma visible ****

    // Texto en capa 4
    final String layer4Text = extraParams.getProperty("layer4Text"); //$NON-NLS-1$

    // Texto en capa 2
    final String layer2Text = extraParams.getProperty("layer2Text"); //$NON-NLS-1$

    // Tipo de letra en capa 2
    int layer2FontFamily;
    try {
        layer2FontFamily = extraParams.getProperty("layer2FontFamily") != null ? //$NON-NLS-1$
                Integer.parseInt(extraParams.getProperty("layer2FontFamily")) : //$NON-NLS-1$
                -1;
    } catch (final Exception e) {
        layer2FontFamily = UNDEFINED;
    }

    // Tamano del tipo de letra en capa 2
    int layer2FontSize;
    try {
        layer2FontSize = extraParams.getProperty("layer2FontSize") != null ? //$NON-NLS-1$
                Integer.parseInt(extraParams.getProperty("layer2FontSize")) : //$NON-NLS-1$
                -1;
    } catch (final Exception e) {
        layer2FontSize = UNDEFINED;
    }

    // Estilo del tipo de letra en capa 2
    int layer2FontStyle;
    try {
        layer2FontStyle = extraParams.getProperty("layer2FontStyle") != null ? //$NON-NLS-1$
                Integer.parseInt(extraParams.getProperty("layer2FontStyle")) : //$NON-NLS-1$
                -1;
    } catch (final Exception e) {
        layer2FontStyle = UNDEFINED;
    }

    // Color del tipo de letra en capa 2
    final String layer2FontColor = extraParams.getProperty("layer2FontColor"); //$NON-NLS-1$

    // ** Fin texto firma visible **
    // *****************************

    // Contrasena del propietario del PDF
    String ownerPassword = extraParams.getProperty("ownerPassword"); //$NON-NLS-1$

    // Contrasena del usuario del PDF
    final String userPassword = extraParams.getProperty("userPassword"); //$NON-NLS-1$

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

    PdfReader pdfReader;
    try {
        if (ownerPassword != null) {
            pdfReader = new PdfReader(inPDF, ownerPassword.getBytes());
        } else if (userPassword != null) {
            pdfReader = new PdfReader(inPDF, userPassword.getBytes());
        } else {
            pdfReader = new PdfReader(inPDF);
        }
    } catch (final BadPasswordException e) {
        // Comprobamos que el signer esta en modo interactivo, y si no lo
        // esta no pedimos contrasena por dialogo, principalmente para no interrumpir un firmado por lotes
        // desatendido
        if (Boolean.TRUE.toString().equalsIgnoreCase(extraParams.getProperty("headLess"))) { //$NON-NLS-1$
            throw new BadPdfPasswordException(e);
        }
        // La contrasena que nos han proporcionada no es buena o no nos
        // proporcionaron ninguna
        ownerPassword = new String(AOUIFactory.getPassword(
                ownerPassword == null ? PDFMessages.getString("AOPDFSigner.0") //$NON-NLS-1$
                        : PDFMessages.getString("AOPDFSigner.1"), //$NON-NLS-1$
                null));
        try {
            pdfReader = new PdfReader(inPDF, ownerPassword.getBytes());
        } catch (final BadPasswordException e2) {
            throw new BadPdfPasswordException(e2);
        }
    } catch (final IOException e) {
        throw new InvalidPdfException(e);
    }

    if (pdfReader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED
            && !Boolean.parseBoolean(extraParams.getProperty("allowSigningCertifiedPdfs"))) { //$NON-NLS-1$
        // Si no permitimos dialogos graficos o directamente hemos indicado que no permitimos firmar PDF certificados lanzamos
        // una excepcion
        if (Boolean.parseBoolean(extraParams.getProperty("headLess")) //$NON-NLS-1$
                || "false".equalsIgnoreCase(extraParams.getProperty("allowSigningCertifiedPdfs"))) { //$NON-NLS-1$ //$NON-NLS-2$
            throw new PdfIsCertifiedException();
        }
        // En otro caso, perguntamos al usuario
        if (AOUIFactory.NO_OPTION == AOUIFactory.showConfirmDialog(null, PDFMessages.getString("AOPDFSigner.8"), //$NON-NLS-1$
                PDFMessages.getString("AOPDFSigner.9"), //$NON-NLS-1$
                AOUIFactory.YES_NO_OPTION, AOUIFactory.WARNING_MESSAGE)) {
            throw new AOCancelledOperationException(
                    "El usuario no ha permitido la firma de un PDF certificado"); //$NON-NLS-1$
        }
    }

    // Los derechos van firmados por Adobe, y como desde iText se invalidan
    // es mejor quitarlos
    pdfReader.removeUsageRights();

    final ByteArrayOutputStream baos = new ByteArrayOutputStream();

    // Activar el atributo de "agregar firma" (cuarto parametro del metodo
    // "PdfStamper.createSignature") hace que se cree una nueva revision del
    // documento y evita que las firmas previas queden invalidadas. Sin embargo, este
    // exige que el PDF no incorpore ningun error, asi que lo mantendremos desactivado
    // para la primera firma y activado para las subsiguientes. Un error incorporado
    // en un PDF erroneo puede quedar subsanado en su version firmada, haciendo
    // posible incorporar nuevas firmas agregando revisiones del documento.
    final PdfStamper stp;
    try {
        stp = PdfStamper.createSignature(pdfReader, // PDF de entrada
                baos, // Salida
                '\0', // Mantener version
                null, // No crear temporal
                pdfReader.getAcroFields().getSignatureNames().size() > 0 // Si hay mas firmas, creo una revision
        );
    } catch (final BadPasswordException e) {
        throw new PdfIsPasswordProtectedException(e);
    }

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

    // PAdES parte 3 seccion 4.7 - Habilitacion para LTV
    stp.getWriter().addDeveloperExtension(new PdfDeveloperExtension(new PdfName("ESIC"), //$NON-NLS-1$
            PdfWriter.PDF_VERSION_1_7, 1));

    // Adjuntos
    if (b64Attachment != null && attachmentFileName != null) {
        byte[] attachment = null;
        try {
            attachment = Base64.decode(b64Attachment);
        } catch (final IOException e) {
            LOGGER.warning("Se ha indicado un adjunto, pero no estaba en formato Base64, se ignorara : " + e); //$NON-NLS-1$
        }
        if (attachment != null) {
            stp.getWriter().addFileAttachment(attachmentDescription, attachment, null, attachmentFileName);
        }
    }

    // iText antiguo
    sap.setRender(PdfSignatureAppearance.SignatureRenderDescription);
    // En iText nuevo seria "sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION);"

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

    // Establecer fecha local del equipo
    if (useSystemDateTime) {
        sap.setSignDate(new GregorianCalendar());
    }

    // Gestion de los cifrados
    if (pdfReader.isEncrypted() && (ownerPassword != null || userPassword != null)) {
        if (Boolean.TRUE.toString().equalsIgnoreCase(extraParams.getProperty("avoidEncryptingSignedPdfs"))) { //$NON-NLS-1$
            LOGGER.info(
                    "Aunque el PDF original estaba encriptado no se encriptara el PDF firmado (se establecio el indicativo 'avoidEncryptingSignedPdfs')" //$NON-NLS-1$
            );
        } else {
            LOGGER.info("El PDF original estaba encriptado, se intentara encriptar tambien el PDF firmado" //$NON-NLS-1$
            );
            try {
                stp.setEncryption(ownerPassword != null ? ownerPassword.getBytes() : null,
                        userPassword != null ? userPassword.getBytes() : null, pdfReader.getPermissions(),
                        pdfReader.getCryptoMode());
            } catch (final DocumentException de) {
                LOGGER.warning("No se ha podido cifrar el PDF destino, se escribira sin contrasena: " + de //$NON-NLS-1$
                );
            }
        }
    }

    // Pagina en donde se imprime la firma
    if (page == LAST_PAGE) {
        page = pdfReader.getNumberOfPages();
    }

    // Posicion de la firma
    final Rectangle signaturePositionOnPage = getSignaturePositionOnPage(extraParams);
    if (signaturePositionOnPage != null && signatureField == null) {
        sap.setVisibleSignature(signaturePositionOnPage, page, null);
    } else if (signatureField != null) {
        sap.setVisibleSignature(signatureField);
    }

    // Localizacion en donde se produce la firma
    if (signatureProductionCity != null) {
        sap.setLocation(signatureProductionCity);
    }

    // Contacto del firmante
    if (signerContact != null) {
        sap.setContact(signerContact);
    }

    // Rubrica de la firma
    if (rubric != null) {
        sap.setImage(rubric);
        sap.setLayer2Text(""); //$NON-NLS-1$
        sap.setLayer4Text(""); //$NON-NLS-1$
    }

    // **************************
    // ** Texto en las capas ****
    // **************************

    // Capa 2
    if (layer2Text != null) {

        sap.setLayer2Text(layer2Text);

        final int layer2FontColorR;
        final int layer2FontColorG;
        final int layer2FontColorB;
        if ("black".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 0;
            layer2FontColorG = 0;
            layer2FontColorB = 0;
        } else if ("white".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 255;
            layer2FontColorG = 255;
            layer2FontColorB = 255;
        } else if ("lightGray".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 192;
            layer2FontColorG = 192;
            layer2FontColorB = 192;
        } else if ("gray".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 128;
            layer2FontColorG = 128;
            layer2FontColorB = 128;
        } else if ("darkGray".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 64;
            layer2FontColorG = 64;
            layer2FontColorB = 64;
        } else if ("red".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 255;
            layer2FontColorG = 0;
            layer2FontColorB = 0;
        } else if ("pink".equalsIgnoreCase(layer2FontColor)) { //$NON-NLS-1$
            layer2FontColorR = 255;
            layer2FontColorG = 175;
            layer2FontColorB = 175;
        } else if (layer2FontColor == null) {
            layer2FontColorR = 0;
            layer2FontColorG = 0;
            layer2FontColorB = 0;
        } else {
            LOGGER.warning("No se soporta el color '" + layer2FontColor //$NON-NLS-1$
                    + "' para el texto de la capa 4, se usara negro"); //$NON-NLS-1$
            layer2FontColorR = 0;
            layer2FontColorG = 0;
            layer2FontColorB = 0;
        }

        com.lowagie.text.Font font;
        try {
            Class<?> colorClass;
            if (Platform.getOS() == OS.ANDROID) {
                colorClass = Class.forName("harmony.java.awt.Color"); //$NON-NLS-1$
            } else {
                colorClass = Class.forName("java.awt.Color"); //$NON-NLS-1$
            }
            final Object color = colorClass.getConstructor(Integer.TYPE, Integer.TYPE, Integer.TYPE)
                    .newInstance(layer2FontColorR, layer2FontColorG, layer2FontColorB);

            font = com.lowagie.text.Font.class
                    .getConstructor(Integer.TYPE, Integer.TYPE, Integer.TYPE, colorClass).newInstance(
                            // Family (COURIER = 0, HELVETICA = 1, TIMES_ROMAN = 2, SYMBOL = 3, ZAPFDINGBATS = 4)
                            layer2FontFamily == UNDEFINED ? COURIER : layer2FontFamily,
                            // Size (DEFAULTSIZE = 12)
                            layer2FontSize == UNDEFINED ? DEFAULT_LAYER_2_FONT_SIZE : layer2FontSize,
                            // Style (NORMAL = 0, BOLD = 1, ITALIC = 2, BOLDITALIC = 3, UNDERLINE = 4, STRIKETHRU = 8)
                            layer2FontStyle == UNDEFINED ? com.lowagie.text.Font.NORMAL : layer2FontStyle,
                            // Color
                            color);

        } catch (Exception e) {
            font = new com.lowagie.text.Font(
                    // Family (COURIER = 0, HELVETICA = 1, TIMES_ROMAN = 2, SYMBOL = 3, ZAPFDINGBATS = 4)
                    layer2FontFamily == UNDEFINED ? COURIER : layer2FontFamily,
                    // Size (DEFAULTSIZE = 12)
                    layer2FontSize == UNDEFINED ? DEFAULT_LAYER_2_FONT_SIZE : layer2FontSize,
                    // Style (NORMAL = 0, BOLD = 1, ITALIC = 2, BOLDITALIC = 3, UNDERLINE = 4, STRIKETHRU = 8)
                    layer2FontStyle == UNDEFINED ? com.lowagie.text.Font.NORMAL : layer2FontStyle,
                    // Color
                    null);
        }
        sap.setLayer2Font(font);
    }

    // Capa 4
    if (layer4Text != null) {
        sap.setLayer4Text(layer4Text);
    }

    // ***************************
    // ** Fin texto en las capas *
    // ***************************

    sap.setCrypto(null, certChain, null, null);

    final PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE,
            signatureSubFilter != null && !"".equals(signatureSubFilter) ? new PdfName(signatureSubFilter) //$NON-NLS-1$
                    : PdfName.ADBE_PKCS7_DETACHED);

    // Fecha de firma
    if (sap.getSignDate() != null) {
        dic.setDate(new PdfDate(sap.getSignDate()));
    }

    dic.setName(PdfPKCS7.getSubjectFields((X509Certificate) certChain[0]).getField("CN")); //$NON-NLS-1$
    if (sap.getReason() != null) {
        dic.setReason(sap.getReason());
    }

    // Lugar de la firma
    if (sap.getLocation() != null) {
        dic.setLocation(sap.getLocation());
    }

    // Contacto del firmante
    if (sap.getContact() != null) {
        dic.setContact(sap.getContact());
    }

    sap.setCryptoDictionary(dic);

    // Certificacion del PDF (NOT_CERTIFIED = 0, CERTIFIED_NO_CHANGES_ALLOWED = 1,
    // CERTIFIED_FORM_FILLING = 2, CERTIFIED_FORM_FILLING_AND_ANNOTATIONS = 3)
    if (certificationLevel != -1) {
        sap.setCertificationLevel(certificationLevel);
    }

    // Reservamos el espacio necesario en el PDF para insertar la firma
    final HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
    exc.put(PdfName.CONTENTS, Integer.valueOf(CSIZE * 2 + 2));

    sap.preClose(exc);

    // ********************************************************************************
    // **************** CALCULO DEL SIGNED DATA ***************************************
    // ********************************************************************************

    // La norma PAdES establece que si el algoritmo de huella digital es SHA1 debe usarse SigningCertificateV2, y en cualquier
    // otro caso deberia usarse SigningCertificateV2
    boolean signingCertificateV2;
    if (extraParams.containsKey("signingCertificateV2")) { //$NON-NLS-1$
        signingCertificateV2 = Boolean.parseBoolean(extraParams.getProperty("signingCertificateV2")); //$NON-NLS-1$
    } else {
        signingCertificateV2 = !"SHA1".equals(AOSignConstants.getDigestAlgorithmName(algorithm)); //$NON-NLS-1$
    }

    byte[] completeCAdESSignature = GenCAdESEPESSignedData.generateSignedData(
            new P7ContentSignerParameters(inPDF, algorithm), true, // omitContent
            new AdESPolicy(extraParams), signingCertificateV2, key, certChain,
            MessageDigest.getInstance(AOSignConstants.getDigestAlgorithmName(algorithm))
                    .digest(AOUtil.getDataFromInputStream(sap.getRangeStream())),
            AOSignConstants.getDigestAlgorithmName(algorithm), true, // Modo PAdES
            PDF_OID,
            extraParams.getProperty("contentDescription") != null //$NON-NLS-1$
                    ? extraParams.getProperty("contentDescription") //$NON-NLS-1$
                    : PDF_DESC);

    //***************** SELLO DE TIEMPO ****************
    final String tsa = extraParams.getProperty("tsaURL"); //$NON-NLS-1$
    URI tsaURL;
    if (tsa != null) {
        try {
            tsaURL = new URI(tsa);
        } catch (final Exception e) {
            LOGGER.warning("Se ha indicado una URL de TSA invalida (" + tsa //$NON-NLS-1$
                    + "), no se anadira sello de tiempo: " + e); //$NON-NLS-1$
            tsaURL = null;
        }
        if (tsaURL != null) {
            final String tsaPolicy = extraParams.getProperty("tsaPolicy"); //$NON-NLS-1$
            if (tsaPolicy == null) {
                LOGGER.warning(
                        "Se ha indicado una URL de TSA pero no una politica, no se anadira sello de tiempo"); //$NON-NLS-1$
            } else {
                final String tsaHashAlgorithm = extraParams.getProperty("tsaHashAlgorithm"); //$NON-NLS-1$
                completeCAdESSignature = new CMSTimestamper(
                        !Boolean.FALSE.toString().equalsIgnoreCase(extraParams.getProperty("tsaRequireCert")), //$NON-NLS-1$
                        tsaPolicy, tsaURL, extraParams.getProperty("tsaUsr"), //$NON-NLS-1$
                        extraParams.getProperty("tsaPwd"), //$NON-NLS-1$
                        extraParams.getProperty("tsaExtensionOid") != null //$NON-NLS-1$
                                && extraParams.getProperty("tsaExtensionValueBase64") != null ? //$NON-NLS-1$
                                        new TsaRequestExtension[] { new TsaRequestExtension(
                                                extraParams.getProperty("tsaExtensionOid"), //$NON-NLS-1$
                                                Boolean.getBoolean(extraParams
                                                        .getProperty("tsaExtensionCritical", "false")), //$NON-NLS-1$ //$NON-NLS-2$
                                                Base64.decode(
                                                        extraParams.getProperty("tsaExtensionValueBase64")) //$NON-NLS-1$
                                        ) } : null).addTimestamp(completeCAdESSignature,
                                                AOAlgorithmID.getOID(AOSignConstants.getDigestAlgorithmName(
                                                        tsaHashAlgorithm != null ? tsaHashAlgorithm : "SHA1"))); //$NON-NLS-1$
            }
        }

    }
    //************** FIN SELLO DE TIEMPO ****************

    // ********************************************************************************
    // *************** FIN CALCULO DEL SIGNED DATA ************************************
    // ********************************************************************************

    final byte[] outc = new byte[CSIZE];
    if (outc.length < completeCAdESSignature.length) {
        throw new AOException("La firma generada tiene un tamano (" + completeCAdESSignature.length //$NON-NLS-1$
                + ") mayor que el permitido (" + outc.length + ")" //$NON-NLS-1$ //$NON-NLS-2$
        );
    }
    final PdfDictionary dic2 = new PdfDictionary();
    System.arraycopy(completeCAdESSignature, 0, outc, 0, completeCAdESSignature.length);
    dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));

    sap.close(dic2);

    return baos.toByteArray();
}

From source file: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/* w ww .  ja v  a 2  s  .  co  m*/
 * @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:eu.europa.ec.markt.dss.signature.pdf.itext.ITextPDFDocTimeSampService.java

License:Open Source License

@SuppressWarnings({ "unchecked", "rawtypes" })
private PdfStamper prepareStamper(InputStream pdfData, OutputStream output, SignatureParameters parameters)
        throws IOException {

    try {//from w  w w  . j a  va  2s . c o m
        PdfReader reader = new PdfReader(pdfData);
        PdfStamper stamper = PdfStamper.createSignature(reader, output, '\0', null, true);

        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setAcro6Layers(true);
        appearance.setRender(PdfSignatureAppearance.SignatureRenderDescription);

        PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("ETSI.RFC3161"));
        // defined in ETSI TS 102 778-4 A.2
        dic.put(PdfName.TYPE, new PdfName("DocTimeStamp"));

        Calendar cal = Calendar.getInstance();
        if (parameters.getSigningDate() != null) {
            cal.setTime(parameters.getSigningDate());
            appearance.setSignDate(cal);
        }
        dic.setDate(new PdfDate(cal));

        appearance.setCryptoDictionary(dic);

        int csize = getSignatureSize();
        HashMap exc = new HashMap();
        exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));

        appearance.preClose(exc);

        return stamper;
    } catch (DocumentException e) {
        throw new IOException(e);
    }

}

From source file:eu.europa.ec.markt.dss.signature.pdf.itext.ITextPDFSignatureService.java

License:Open Source License

@SuppressWarnings({ "unchecked", "rawtypes" })
private PdfStamper prepareStamper(InputStream pdfData, OutputStream output, SignatureParameters parameters)
        throws IOException, DocumentException {

    PdfReader reader = new PdfReader(pdfData);
    PdfStamper stp = PdfStamper.createSignature(reader, output, '\0', null, true);

    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    sap.setAcro6Layers(true);/*from w w  w  .  j  ava  2  s.c o  m*/
    sap.setRender(PdfSignatureAppearance.SignatureRenderDescription);

    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("ETSI.CAdES.detached"));
    Calendar cal = Calendar.getInstance();
    cal.setTime(parameters.getSigningDate());
    sap.setSignDate(cal);
    dic.setDate(new PdfDate(cal));

    if (parameters.getReason() != null) {
        dic.setReason(parameters.getReason());
    }
    if (parameters.getLocation() != null) {
        dic.setLocation(parameters.getLocation());
    }
    if (parameters.getContactInfo() != null) {
        dic.setContact(parameters.getContactInfo());
    }

    sap.setCryptoDictionary(dic);

    int csize = getSignatureSize();
    HashMap exc = new HashMap();
    exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));

    sap.preClose(exc);

    return stp;
}

From source file:eu.europa.ec.markt.dss.signature.pdf.ITextPDFDocTimeSampService.java

License:Open Source License

@SuppressWarnings({ "unchecked", "rawtypes" })
private PdfStamper prepareStamper(InputStream pdfData, OutputStream output, SignatureParameters parameters)
        throws IOException, DocumentException {

    PdfReader reader = new PdfReader(pdfData);
    PdfStamper stp = PdfStamper.createSignature(reader, output, '\0', null, true);

    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    sap.setAcro6Layers(true);/*from   ww w.ja v a 2s  .  c o m*/
    sap.setRender(PdfSignatureAppearance.SignatureRenderDescription);

    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("ETSI.RFC3161"));
    // defined in ETSI TS 102 778-4 A.2
    dic.put(PdfName.TYPE, new PdfName("DocTimeStamp"));

    Calendar cal = Calendar.getInstance();
    if (parameters.getSigningDate() != null) {
        cal.setTime(parameters.getSigningDate());
        sap.setSignDate(cal);
    }
    dic.setDate(new PdfDate(cal));

    sap.setCryptoDictionary(dic);

    int csize = getSignatureSize();
    HashMap exc = new HashMap();
    exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));

    sap.preClose(exc);

    return stp;
}

From source file:eu.europa.ec.markt.dss.signature.pdf.StatefulITextPDFSignatureService.java

License:Open Source License

@SuppressWarnings({ "unchecked", "rawtypes" })
private PdfStamper prepareStamper(InputStream pdfData, OutputStream output, SignatureParameters parameters)
        throws IOException, DocumentException {

    if (stp != null) {
        return stp;
    }//w w  w  .  ja v  a 2s.  c  o m

    PdfReader reader = new PdfReader(pdfData);
    stp = PdfStamper.createSignature(reader, output, '\0', null, true);

    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    sap.setAcro6Layers(true);
    sap.setLayer2Text("");
    if (parameters.getSignatureAppearance() != null) {
        sap.setRender(PdfSignatureAppearance.SignatureRenderGraphic);
        sap.setImage(null);
        PdfReader stampReader = new PdfReader(parameters.getSignatureAppearance());
        PdfTemplate stamp = stp.getWriter().getImportedPage(stampReader, 1);
        //stamp.setBoundingBox(new Rectangle(200, 100));
        sap.setTemplate(stamp);
        sap.setSignatureGraphic(Image.getInstance(stamp));

        float[] pos = parameters.getSignaturePosition();
        Rectangle rect = new Rectangle(pos[0], pos[1], pos[2], pos[3]);
        sap.setVisibleSignature(rect, 1, parameters.getSignatureName());
    } else {
        sap.setRender(PdfSignatureAppearance.SignatureRenderDescription);
    }

    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("ETSI.CAdES.detached"));
    Calendar cal = Calendar.getInstance();
    cal.setTime(parameters.getSigningDate());
    sap.setSignDate(cal);
    dic.setDate(new PdfDate(cal));

    if (parameters.getReason() != null) {
        dic.setReason(parameters.getReason());
    }
    if (parameters.getLocation() != null) {
        dic.setLocation(parameters.getLocation());
    }
    if (parameters.getContactInfo() != null) {
        dic.setContact(parameters.getContactInfo());
    }

    sap.setCryptoDictionary(dic);

    int csize = getSignatureSize();
    HashMap exc = new HashMap();
    exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));

    sap.preClose(exc);

    return stp;
}

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

License:Mozilla Public License

/**
 * Signs a single file.//from  w  w  w .j  av a  2  s  .  c o m
 * 
 * @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.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  w w . j  a v a2  s  . co  m
    final List<Certificate> includedCerts = includedCertificates(certs);
    Certificate[] certChain = includedCerts.toArray(new Certificate[includedCerts.size()]);
    PrivateKey privKey = crypto.getPrivateKey();

    // need to check digest algorithms for DSA private key at signing
    // time since we can't be sure what key a configured alias selector gives back
    if (privKey instanceof DSAPrivateKey) {
        if (!"SHA1".equals(digestAlgorithm)) {
            throw new IllegalRequestException(
                    "Only SHA1 is permitted as digest algorithm for DSA private keys");
        }
    }

    PdfReader reader = new PdfReader(pdfbytes, password);
    boolean appendMode = true; // TODO: This could be good to have as a property in the future

    int pdfVersion;

    try {
        pdfVersion = Integer.parseInt(Character.toString(reader.getPdfVersion()));
    } catch (NumberFormatException e) {
        pdfVersion = 0;
    }

    if (LOG.isDebugEnabled()) {
        LOG.debug("PDF version: " + pdfVersion);
    }

    // Don't certify already certified documents
    if (reader.getCertificationLevel() != PdfSignatureAppearance.NOT_CERTIFIED
            && params.getCertification_level() != PdfSignatureAppearance.NOT_CERTIFIED) {
        throw new IllegalRequestException("Will not certify an already certified document");
    }

    // Don't sign documents where the certification does not allow it
    if (reader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED
            || reader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_FORM_FILLING) {
        throw new IllegalRequestException("Will not sign a certified document where signing is not allowed");
    }

    Permissions currentPermissions = Permissions.fromInt(reader.getPermissions());

    if (params.getSetPermissions() != null && params.getRemovePermissions() != null) {
        throw new SignServerException("Signer " + workerId + " missconfigured. Only one of " + SET_PERMISSIONS
                + " and " + REMOVE_PERMISSIONS + " should be specified.");
    }

    Permissions newPermissions;
    if (params.getSetPermissions() != null) {
        newPermissions = params.getSetPermissions();
    } else if (params.getRemovePermissions() != null) {
        newPermissions = currentPermissions.withRemoved(params.getRemovePermissions());
    } else {
        newPermissions = null;
    }

    Permissions rejectPermissions = Permissions.fromSet(params.getRejectPermissions());
    byte[] userPassword = reader.computeUserPassword();
    int cryptoMode = reader.getCryptoMode();
    if (LOG.isDebugEnabled()) {
        StringBuilder buff = new StringBuilder();
        buff.append("Current permissions: ").append(currentPermissions).append("\n")
                .append("Remove permissions: ").append(params.getRemovePermissions()).append("\n")
                .append("Reject permissions: ").append(rejectPermissions).append("\n")
                .append("New permissions: ").append(newPermissions).append("\n").append("userPassword: ")
                .append(userPassword == null ? "null" : "yes").append("\n").append("ownerPassword: ")
                .append(password == null ? "no" : (isUserPassword(reader, password) ? "no" : "yes"))
                .append("\n").append("setOwnerPassword: ")
                .append(params.getSetOwnerPassword() == null ? "no" : "yes").append("\n").append("cryptoMode: ")
                .append(cryptoMode);
        LOG.debug(buff.toString());
    }

    if (appendMode && (newPermissions != null || params.getSetOwnerPassword() != null)) {
        appendMode = false;
        if (LOG.isDebugEnabled()) {
            LOG.debug("Changing appendMode to false to be able to change permissions");
        }
    }

    ByteArrayOutputStream fout = new ByteArrayOutputStream();

    // increase PDF version if needed by digest algorithm
    final char updatedPdfVersion;
    if (minimumPdfVersion > pdfVersion) {
        updatedPdfVersion = Character.forDigit(minimumPdfVersion, 10);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Need to upgrade PDF to version 1." + updatedPdfVersion);
        }

        // check that the document isn't already signed 
        // when trying to upgrade version
        final AcroFields af = reader.getAcroFields();
        final List<String> sigNames = af.getSignatureNames();

        if (!sigNames.isEmpty()) {
            // TODO: in the future we might want to support
            // a fallback option in this case to allow re-signing using the same version (using append)
            throw new IllegalRequestException(
                    "Can not upgrade an already signed PDF and a higher version is required to support the configured digest algorithm");
        }

        appendMode = false;
    } else {
        updatedPdfVersion = '\0';
    }

    PdfStamper stp = PdfStamper.createSignature(reader, fout, updatedPdfVersion, null, appendMode);
    PdfSignatureAppearance sap = stp.getSignatureAppearance();

    // Set the new permissions
    if (newPermissions != null || params.getSetOwnerPassword() != null) {
        if (cryptoMode < 0) {
            cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting default encryption algorithm");
            }
        }
        if (newPermissions == null) {
            newPermissions = currentPermissions;
        }
        if (params.getSetOwnerPassword() != null) {
            password = params.getSetOwnerPassword().getBytes("ISO-8859-1");
        } else if (isUserPassword(reader, password)) {
            // We do not have an owner password so lets use a random one
            password = new byte[16];
            random.nextBytes(password);
            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting random owner password");
            }
        }
        stp.setEncryption(userPassword, password, newPermissions.asInt(), cryptoMode);
        currentPermissions = newPermissions;
    }

    // Reject if any permissions are rejected and the document does not use a permission password
    // or if it contains any of the rejected permissions
    if (rejectPermissions.asInt() != 0) {
        if (cryptoMode < 0 || currentPermissions.containsAnyOf(rejectPermissions)) {
            throw new IllegalRequestException("Document contains permissions not allowed by this signer");
        }
    }

    // include signer certificate crl inside cms package if requested
    CRL[] crlList = null;
    if (params.isEmbed_crl()) {
        crlList = getCrlsForChain(certs);
    }
    sap.setCrypto(null, certChain, crlList, PdfSignatureAppearance.SELF_SIGNED);

    // add visible signature if requested
    if (params.isAdd_visible_signature()) {
        int signaturePage = getPageNumberForSignature(reader, params);
        sap.setVisibleSignature(new com.lowagie.text.Rectangle(params.getVisible_sig_rectangle_llx(),
                params.getVisible_sig_rectangle_lly(), params.getVisible_sig_rectangle_urx(),
                params.getVisible_sig_rectangle_ury()), signaturePage, null);

        // set custom image if requested
        if (params.isUse_custom_image()) {
            sap.setAcro6Layers(true);
            PdfTemplate n2 = sap.getLayer(2);
            params.getCustom_image().setAbsolutePosition(0, 0);
            n2.addImage(params.getCustom_image());
        }
    }

    // Certification level
    sap.setCertificationLevel(params.getCertification_level());

    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
    dic.setReason(params.getReason());
    dic.setLocation(params.getLocation());
    dic.setDate(new PdfDate(Calendar.getInstance()));

    sap.setCryptoDictionary(dic);

    // add timestamp to signature if requested
    TSAClient tsc = null;
    if (params.isUse_timestamp()) {
        final String tsaUrl = params.getTsa_url();

        if (tsaUrl != null) {
            tsc = getTimeStampClient(params.getTsa_url(), params.getTsa_username(), params.getTsa_password());
        } else {
            tsc = new InternalTSAClient(getWorkerSession(), params.getTsa_worker(), params.getTsa_username(),
                    params.getTsa_password());
        }
    }

    // embed ocsp response in cms package if requested
    // for ocsp request to be formed there needs to be issuer certificate in
    // chain
    byte[] ocsp = null;
    if (params.isEmbed_ocsp_response() && certChain.length >= 2) {
        String url;
        try {
            url = PdfPKCS7.getOCSPURL((X509Certificate) certChain[0]);
            if (url != null && url.length() > 0) {
                ocsp = new OcspClientBouncyCastle((X509Certificate) certChain[0],
                        (X509Certificate) certChain[1], url).getEncoded();
            }
        } catch (CertificateParsingException e) {
            throw new SignServerException("Error getting OCSP URL from certificate", e);
        }

    }

    PdfPKCS7 sgn;
    try {
        sgn = new PdfPKCS7(privKey, certChain, crlList, digestAlgorithm, null, false);
    } catch (InvalidKeyException e) {
        throw new SignServerException("Error constructing PKCS7 package", e);
    } catch (NoSuchProviderException e) {
        throw new SignServerException("Error constructing PKCS7 package", e);
    } catch (NoSuchAlgorithmException e) {
        throw new SignServerException("Error constructing PKCS7 package", e);
    }

    MessageDigest messageDigest;
    try {
        messageDigest = MessageDigest.getInstance(digestAlgorithm);
    } catch (NoSuchAlgorithmException e) {
        throw new SignServerException("Error creating " + digestAlgorithm + " digest", e);
    }

    Calendar cal = Calendar.getInstance();

    // calculate signature size
    if (contentEstimated == 0) {
        contentEstimated = calculateEstimatedSignatureSize(certChain, tsc, ocsp, crlList);
    }

    byte[] encodedSig = calculateSignature(sgn, contentEstimated, messageDigest, cal, params, certChain, tsc,
            ocsp, sap);

    if (LOG.isDebugEnabled()) {
        LOG.debug("Estimated size: " + contentEstimated);
        LOG.debug("Encoded length: " + encodedSig.length);
    }

    if (contentEstimated + 2 < encodedSig.length) {
        if (!secondTry) {
            int contentExact = encodedSig.length;
            LOG.warn(
                    "Estimated signature size too small, usinging accurate calculation (resulting in an extra signature computation).");

            if (LOG.isDebugEnabled()) {
                LOG.debug("Estimated size: " + contentEstimated + ", actual size: " + contentExact);
            }

            // try signing again
            return addSignatureToPDFDocument(crypto, params, pdfbytes, password, contentExact, request,
                    context);
        } else {
            // if we fail to get an accurate signature size on the second attempt, bail out (this shouldn't happen)
            throw new SignServerException("Failed to calculate signature size");
        }
    }

    byte[] paddedSig = new byte[contentEstimated];
    System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);

    PdfDictionary dic2 = new PdfDictionary();
    dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
    sap.close(dic2);
    reader.close();

    fout.close();
    return fout.toByteArray();
}

From source file:si.vsrs.cif.svev.example.utils.PDFSignature.java

License:EUPL

public File signPDF(File document, InputStream keystore, String password, String keyPassord,
        String keystoreType, String alias, boolean bshowVisualization) {
    if (document == null || !document.exists()) {
        throw new RuntimeException("Error reading pdf");
    }//from   w w w .java  2s. co m

    String name = document.getName();
    String substring = name.substring(0, name.lastIndexOf("."));

    File outputDocument = new File(document.getParent(), substring + "_signed.pdf");

    try (FileInputStream fis = new FileInputStream(document);
            FileOutputStream fout = new FileOutputStream(outputDocument)) {

        KeyStore ks = KeyStore.getInstance(keystoreType);
        ks.load(keystore, password.toCharArray());
        PrivateKey key = (PrivateKey) ks.getKey(alias, keyPassord.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        X509Certificate xcert = (X509Certificate) chain[0];
        PdfReader reader = new PdfReader(fis);

        char tmpPdfVersion = '\0'; // default version - the same as input
        final PdfStamper stp = PdfStamper.createSignature(reader, fout, tmpPdfVersion, null, true);
        final PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
        sap.setReason("Testni podpis");
        sap.setLocation("Maribor");
        sap.setContact(xcert.getSubjectDN().getName());

        //            sap.setLayer2Text("");
        //          sap.setLayer4Text("");
        sap.setAcro6Layers(true); // --:> 

        Rectangle rc = reader.getPageSize(1);
        if (bshowVisualization) {
            sap.setVisibleSignature(new Rectangle(5, rc.getHeight() - 40, 240, rc.getHeight() - 5), 1, null);
        }

        final PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));

        dic.setReason(sap.getReason());
        dic.setLocation(sap.getLocation());
        dic.setContact(sap.getContact());
        dic.setDate(new PdfDate(sap.getSignDate()));
        sap.setCryptoDictionary(dic);
        final int contentEstimated = 15000;
        final HashMap<PdfName, Integer> exc = new HashMap<>();
        exc.put(PdfName.CONTENTS, contentEstimated * 2 + 2);
        sap.preClose(exc);

        PdfPKCS7 sgn = new PdfPKCS7(key, chain, null, "SHA-256", null, false);
        InputStream data = sap.getRangeStream();
        final MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        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 sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, null);
        sgn.update(sh, 0, sh.length);

        byte[] encodedSig = sgn.getEncodedPKCS7(hash, cal, null, null);

        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);
    } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException
            | UnrecoverableKeyException | DocumentException | InvalidKeyException | NoSuchProviderException
            | SignatureException ex) {
        throw new RuntimeException(ex.getMessage(), ex);
    }

    return outputDocument;
}