List of usage examples for com.lowagie.text.pdf PdfSignatureAppearance setCrypto
public void setCrypto(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, PdfName filter)
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ónicas, consistentes en los datos * a ser firmados con CAdES o PKCS#7 y los metadatos necesarios para su correcta inserció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ámetros adicionales de la firma * @return Datos PDF relevantes en cuanto a las firmas electró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í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(); }