Java tutorial
/* Copyright (C) 2011 [Gobierno de Espana] * This file is part of "Cliente @Firma". * "Cliente @Firma" is free software; you can redistribute it and/or modify it under the terms of: * - the GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, or (at your option) any later version. * - or The European Software License; either version 1.1 or (at your option) any later version. * Date: 11/01/11 * You may contact the copyright holder at: soporte.afirma5@mpt.es */ package es.gob.afirma.envelopers.cms; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyStore.PrivateKeyEntry; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.logging.Logger; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import es.gob.afirma.core.AOException; import es.gob.afirma.core.AOInvalidFormatException; import es.gob.afirma.core.ciphers.AOCipherConfig; import es.gob.afirma.core.ciphers.CipherConstants.AOCipherAlgorithm; import es.gob.afirma.core.envelopers.AOEnveloper; import es.gob.afirma.core.signers.AOSignConstants; import es.gob.afirma.signers.cms.AOCMSSigner; import es.gob.afirma.signers.pkcs7.P7ContentSignerParameters; /** Funcionalidad de sobres digitales con CAdES. */ public class AOCMSEnveloper implements AOEnveloper { /** Envoltorio binario de tipo Data (datos envueltos en un envoltorio * PKCS#7). */ public static final String CMS_CONTENTTYPE_DATA = "Data"; //$NON-NLS-1$ /** Firma binaria de tipo Signed Data */ public static final String CMS_CONTENTTYPE_SIGNEDDATA = "SignedData"; //$NON-NLS-1$ /** Envoltorio binario de tipo Digest. */ public static final String CMS_CONTENTTYPE_DIGESTEDDATA = "DigestedData"; //$NON-NLS-1$ /** Envoltario binario de tipo AuthenticatedEnvelopedData. */ public static final String CMS_CONTENTTYPE_COMPRESSEDDATA = "CompressedData"; //$NON-NLS-1$ /** Firma binaria de tipo Encrypted Data */ public static final String CMS_CONTENTTYPE_ENCRYPTEDDATA = "EncryptedData"; //$NON-NLS-1$ /** Envoltorio binario de tipo Enveloped (sobre digital). */ public static final String CMS_CONTENTTYPE_ENVELOPEDDATA = "EnvelopedData"; //$NON-NLS-1$ /** Envoltorio binario de tipo Signed and Enveloped. */ public static final String CMS_CONTENTTYPE_SIGNEDANDENVELOPEDDATA = "SignedAndEnvelopedData"; //$NON-NLS-1$ /** Envoltario binario de tipo AuthenticatedData. */ public static final String CMS_CONTENTTYPE_AUTHENTICATEDDATA = "AuthenticatedData"; //$NON-NLS-1$ /** Envoltario binario de tipo AuthenticatedEnvelopedData. */ public static final String CMS_CONTENTTYPE_AUTHENVELOPEDDATA = "AuthEnvelopedData"; //$NON-NLS-1$ /** Envoltorio binario por defecto. */ public static final String DEFAULT_CMS_CONTENTTYPE = CMS_CONTENTTYPE_ENVELOPEDDATA; //TODO /** Método para la generación de envolturas de datos. Los tipos de * envoltura definidos para CMS son: <br> * <ul> * <li>Data</li> * <li>Signed Data</li> * <li>Digested Data</li> * <li>Enveloped Data</li> * <li>Signed and Enveloped Data</li> * </ul> * Para la generación de la clave interna se utiliza por defecto el * algoritmo AES. * En el caso de que sea tipo "Enveloped data" o * "Signed and enveloped data", la clave se generará usando el * algoritmo pasado como parámetro. Dicha clave se cifrará * después con la clave pública del certificado que identifica * al usuario destinatario. * Nota: El parámetro algorithm no es el agoritmo de cifrado, es para * el digestAlgorithm usado en los "Unsigned Attributes". * @param data Datos que se desean envolver. * @param digestAlgorithm Algoritmo a usar para la envoltura (SHA1withRSA, MD5withRSA,...) * @param type Tipo de envoltura que se quiere hacer. * @param keyEntry Clave privada a usar para firmar. * @param certDest Certificados de los usuarios a los que va destinado el sobre digital * @param cipherAlgorithm Algoritmo utilizado para cifrar * @param extraParams Parámetros adicionales * @return Envoltorio CADES * @throws AOException Cuando ocurre cualquier problema en el proceso */ @Override public byte[] envelop(final byte[] data, final String digestAlgorithm, final String type, final PrivateKeyEntry keyEntry, final X509Certificate[] certDest, final AOCipherAlgorithm cipherAlgorithm, final String dataType, final Properties extraParams) throws AOException { return null; } /** Cifra datos usando para ello una clave de cifrado.<br> * Se usará por defecto el algoritmo de cifrado "AES". * La clave usada para cifrar el contenido puede ser tanto un password como * una clave privada codificada. * En el caso de que sea una clave codificada en base 64, se usará * como algoritmos los tipo AES, DES ... En el caso de que sea un password, * se usará un algoritmo de tipo PBE. * Nota: El digestAlgorithm no es el agoritmo de cifrado, es el algoritmo de * huella digital usado en los "Unsigned Attributes". * @param data * Datos a envolver. * @param digestAlgorithm * Algoritmo a usar para la envoltura (SHA1withRSA, MD5withRSA,...) * @param key * Puede ser una clave codificada o una contraseña usada * para cifrar el contenido. * @param cipherAlgorithm * Algoritmo a usar para los cifrados * @param dataType OID del tipo de datos a encriptar * @return Contenido firmado * @throws AOException * Cuando ocurre cualquier problema durante el proceso */ @Override public byte[] encrypt(final byte[] data, final String digestAlgorithm, final String key, final AOCipherAlgorithm cipherAlgorithm, final String dataType) throws AOException { // Comprobamos que el archivo a cifrar no sea nulo. if (data == null) { throw new IllegalArgumentException("Los datos a cifrar no pueden ser nulo."); //$NON-NLS-1$ } return null; } /** Tipo de los datos contenidos en la envoltura. Siempre data por * estándar. */ private static final String DATA_TYPE_OID = PKCSObjectIdentifiers.data.getId(); /** Algoritmo de firma. */ private String signatureAlgorithm = AOSignConstants.DEFAULT_SIGN_ALGO; /** Atributos firmados que se desean agregar a los envoltorios firmados. */ private final Map<String, byte[]> attrib = new HashMap<String, byte[]>(); /** Atributos que no requieren firma y se desean agregar a todos los * envoltorios que los soporten. */ private final Map<String, byte[]> uattrib = new HashMap<String, byte[]>(); /** Clave para el descifrado de los datos de un envoltorio EncryptedData. Si * se utiliza un algoritmo PBE de cifrado, será una contraseña * en texto plano. Si es otro algoritmo será su clave en base 64. */ private String cipherKey = null; /** Configura un atributo firmado para agregarlo a un envoltorio. * @param oid * Object Identifier. Identificador del objeto a introducir. * @param value * Valor asignado */ public void addSignedAttribute(final String oid, final byte[] value) { this.attrib.put(oid, value); } /** Configura un atributo no firmado para agregarlo a un envoltorio. * @param oid * Object Identifier. Identificador del atributo a introducir. * @param value * Valor asignado */ public void addUnsignedAttribute(final String oid, final byte[] value) { this.uattrib.put(oid, value); } /** Crea un envoltorio CMS de tipo Data. * @param content Datos que se desean envolver. * @return Envoltorio Data. * @throws IOException En caso de error en la lectura o tratamiento de datos */ static byte[] createCMSData(final byte[] content) throws IOException { return CMSData.genData(content); } /** Crea un envoltorio CMS de tipo DigestedData. * @param content * Datos que se desean envolver. * @return Envoltorio DigestedData. * @throws IOException * Error en la lectura de datos. * @throws NoSuchAlgorithmException * Cuando el algoritmo de cifrado indicado no está * soportado. */ byte[] createCMSDigestedData(final byte[] content) throws IOException, NoSuchAlgorithmException { return CMSDigestedData.genDigestedData(content, this.signatureAlgorithm, DATA_TYPE_OID); } /** Crea un envoltorio CMS de tipo CompressedData. * @param content * Datos que se desean envolver. * @return Envoltorio Compressed Data. * @throws IOException En caso de error en la lectura o tratamiento de datos */ static byte[] createCMSCompressedData(final byte[] content) throws IOException { return CMSCompressedData.genCompressedData(content); } /** Crea un envoltorio CMS de tipo EncryptedData. * @param content * Contenido a envolver * @param cipherConfig * Configuración del cifrado del envoltorio * @param key * Clave de envoltura * @return Envoltorio EncryptedData. * @throws NoSuchAlgorithmException * Cuando el algoritmo de cifrado indicado no está * soportado. * @throws IOException * Cuando se produce algun error al codificar los datos. */ public byte[] createCMSEncryptedData(final byte[] content, final AOCipherConfig cipherConfig, final Key key) throws NoSuchAlgorithmException, IOException { return CMSEncryptedData.genEncryptedData(content, this.signatureAlgorithm, cipherConfig, key, DATA_TYPE_OID, this.uattrib); } /** Crea un envoltorio CMS de tipo EnvelopedData. * @param content * Contenido que se desea ensobrar. * @param ke * Clave privada del remitente (sólo si se quiere indicar * remitente). * @param cipherConfig * Configuración para el cifrado de datos. * @param recipientsCerts * Destinatarios del sobre electrónico. * @param keySize Tamaño de la clave AES de cifrado * @return Envoltorio EnvelopedData. * @throws NoSuchAlgorithmException * Cuando el algoritmo de cifrado indicado no está * soportado. * @throws IOException * Error en la escritura de datos. * @throws CertificateEncodingException * Cuando el certificado del remitente no es válido. * @throws AOException Cuando ocurre un error al generar el núcleo del envoltorio. * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws InvalidKeyException Si la clave proporcionada no es válida */ public byte[] createCMSEnvelopedData(final byte[] content, final PrivateKeyEntry ke, final AOCipherConfig cipherConfig, final X509Certificate[] recipientsCerts, final Integer keySize) throws NoSuchAlgorithmException, CertificateEncodingException, IOException, AOException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { // Si se establecion un remitente if (ke != null) { return new CMSEnvelopedData().genEnvelopedData( AOCMSEnveloper.createContentSignerParementers(content, this.signatureAlgorithm), (X509Certificate[]) ke.getCertificateChain(), cipherConfig, recipientsCerts, DATA_TYPE_OID, this.uattrib, keySize); } // Si no se establecio remitente return new CMSEnvelopedData().genEnvelopedData(content, this.signatureAlgorithm, cipherConfig, recipientsCerts, DATA_TYPE_OID, this.uattrib, keySize); } /** Crea un envoltorio CMS de tipo SignedAndEnvelopedData. * @param content Contenido que se desea ensobrar. * @param ke Clave privada del remitente. * @param cipherConfig Configuración para el cifrado de datos. * @param recipientsCerts Destinatarios del sobre electrónico. * @param keySize Tamaño de la clave AES de cifrado * @return Envoltorio SignedAndEnvelopedData. * @throws NoSuchAlgorithmException Cuando el algoritmo de cifrado indicado no está soportado. * @throws IOException Cuando se produce un error en la escritura de datos. * @throws CertificateEncodingException Cuando el certificado del remitente no es válido. * @throws AOException Cuando ocurre un error al generar el núcleo del envoltorio. * @throws SignatureException CUando ocuren problemas firmando el sobre digital * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws InvalidKeyException Si la clave proporcionada no es válida */ public byte[] createCMSSignedAndEnvelopedData(final byte[] content, final PrivateKeyEntry ke, final AOCipherConfig cipherConfig, final X509Certificate[] recipientsCerts, final Integer keySize) throws CertificateEncodingException, NoSuchAlgorithmException, IOException, AOException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, SignatureException { return new CMSSignedAndEnvelopedData().genSignedAndEnvelopedData( AOCMSEnveloper.createContentSignerParementers(content, this.signatureAlgorithm), (X509Certificate[]) ke.getCertificateChain(), cipherConfig, recipientsCerts, DATA_TYPE_OID, ke, this.attrib, this.uattrib, keySize); } /** Crea un envoltorio CMS de tipo <code>AuthenticatedData</code>. * @param content Contenido que se desea ensobrar. * @param ke Clave privada del remitente. * @param cipherConfig Configuración para el cifrado de datos. * @param recipientsCerts Destinatarios del sobre electrónico. * @param keySize Tamaño de la clave AES. * @return Envoltorio <code>AuthenticatedData</code>. * @throws NoSuchAlgorithmException * Cuando el algoritmo de cifrado indicado no está * soportado. * @throws IOException Cuando ocurre un error en la escritura de datos. * @throws CertificateEncodingException Cuando el certificado del remitente no es válido. * @throws AOException Cuando ocurre un error al generar el núcleo del envoltorio. * @throws InvalidKeyException Si la clave proporcionada no es válida * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo * @throws NoSuchPaddingException Si no se soporta algún método de relleno */ byte[] createCMSAuthenticatedData(final byte[] content, final PrivateKeyEntry ke, final AOCipherConfig cipherConfig, final X509Certificate[] recipientsCerts, final Integer keySize) throws CertificateEncodingException, NoSuchAlgorithmException, IOException, AOException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { return CMSAuthenticatedData.genAuthenticatedData( AOCMSEnveloper.createContentSignerParementers(content, this.signatureAlgorithm), // ContentSignerParameters (X509Certificate[]) ke.getCertificateChain(), // Certificados del firmante (remitente) null, // Algoritmo de autenticacion (usamos el por defecto) cipherConfig, // Configuracion del cipher recipientsCerts, // certificados destino DATA_TYPE_OID, // dataType true, // applySigningTime, this.attrib, // atributos firmados this.uattrib, // atributos no firmados keySize // Tamano de la clave AES ); } /** Crea un envoltorio CMS de tipo AuthenticatedEnvelopedData. * @param content * Contenido que se desea ensobrar. * @param ke * Clave privada del remitente. * @param cipherConfig * Configuración para el cifrado de datos. * @param recipientsCerts * Destinatarios del sobre electrónico. * @param keySize Tamaño de la clave AES de cifrado * @return Envoltorio AuthenticatedEnvelopedData. * @throws NoSuchAlgorithmException * Cuando el algoritmo de cifrado indicado no está * soportado. * @throws IOException * Error en la escritura de datos. * @throws CertificateEncodingException * Cuando el certificado del remitente no es válido. * @throws AOException * Cuando ocurre un error al generar el núcleo del envoltorio. * @throws InvalidKeyException Si la clave proporcionada no es válida * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo * @throws NoSuchPaddingException Si no se soporta algún método de relleno */ public byte[] createCMSAuthenticatedEnvelopedData(final byte[] content, final PrivateKeyEntry ke, final AOCipherConfig cipherConfig, final X509Certificate[] recipientsCerts, final Integer keySize) throws CertificateEncodingException, NoSuchAlgorithmException, IOException, AOException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { return CMSAuthenticatedEnvelopedData.genAuthenticatedEnvelopedData( AOCMSEnveloper.createContentSignerParementers(content, this.signatureAlgorithm), // ContentSignerParameters (X509Certificate[]) ke.getCertificateChain(), // Certificados del firmante (remitente) null, // Algoritmo de autenticacion (usamos el por defecto) cipherConfig, // Configuracion del cipher recipientsCerts, // certificados destino DATA_TYPE_OID, // dataType true, // applySigningTime, this.attrib, // atributos firmados this.uattrib, // atributos no firmados keySize); } /** Genera el bloque de datos con la información del remitente de un * mensaje. * @param content * Mensaje. * @param digestAlgorithm * Algoritmo de huella digital. * @return Bloque de datos con la información del remitente. */ private static P7ContentSignerParameters createContentSignerParementers(final byte[] content, final String digestAlgorithm) { return new P7ContentSignerParameters(content, digestAlgorithm); } /** Agrega un nuevo remitente a un envoltorio CMS compatible. * @param envelop * Envoltorio original. * @param ke * Referencia a la clave privada del certificado del remitente. * @return Envoltorio con el nuevo remitente. * @throws AOException * Cuando se produce un error al agregar el nuevo remitente. * @throws IOException Cuando ocurre algún error en la lectura de los datos. * @throws CertificateEncodingException Cuando el certificado del remitente es inválido * @throws AOInvalidFormatException * Tipo de envoltorio no soportado. */ public static byte[] addOriginator(final byte[] envelop, final PrivateKeyEntry ke) throws AOException, IOException, CertificateEncodingException { final String contentInfo; if (ValidateCMS.isCMSEnvelopedData(envelop)) { contentInfo = CMS_CONTENTTYPE_ENVELOPEDDATA; } else if (ValidateCMS.isCMSSignedAndEnvelopedData(envelop)) { contentInfo = CMS_CONTENTTYPE_SIGNEDANDENVELOPEDDATA; } else if (ValidateCMS.isCMSAuthenticatedEnvelopedData(envelop)) { contentInfo = CMS_CONTENTTYPE_AUTHENVELOPEDDATA; } else { throw new AOInvalidFormatException( "Los datos proporcionado no son un envoltorio que soporte multiples remitentes"); //$NON-NLS-1$ } return addOriginator(envelop, contentInfo, ke); } /** Agrega los datos de un remitente adicional a un envoltorio compatible. * Los envoltorios que admiten más de un remitente son: * <ul> * <li>Enveloped Data</li> * <li>Authenticated Data</li> * <li>Authenticated And Enveloped Data</li> * <li>Signed And Enveloped Data</li> * </ul> * @param envelop Estructura a la que se le desea agregar un remitente. * @param contentInfo Tipo de contenido que se desea envolver. * @param ke Referencia a la clave privada del certificado del remitente. * @return Estructura (sobre) con el remitente añadido. * @throws AOException Cuando ocurre un error al agregar el remitente a la * estructura. * @throws IOException Cuando ocurre algún error en la lectura de los datos. * @throws CertificateEncodingException Si el certificado del remitente es inválido * @throws IllegalArgumentException Cuando se indica un contentInfo no compatible con * mútiples remitentes. */ private static byte[] addOriginator(final byte[] envelop, final String contentInfo, final PrivateKeyEntry ke) throws AOException, IOException, CertificateEncodingException { byte[] newEnvelop; if (contentInfo.equals(CMS_CONTENTTYPE_ENVELOPEDDATA)) { newEnvelop = CMSEnvelopedData.addOriginatorInfo(envelop, (X509Certificate[]) ke.getCertificateChain()); } else if (contentInfo.equals(CMS_CONTENTTYPE_SIGNEDANDENVELOPEDDATA)) { newEnvelop = new AOCMSSigner().cosign(envelop, AOSignConstants.DEFAULT_SIGN_ALGO, ke.getPrivateKey(), ke.getCertificateChain(), null); } else if (contentInfo.equals(CMS_CONTENTTYPE_AUTHENVELOPEDDATA)) { newEnvelop = CMSAuthenticatedEnvelopedData.addOriginatorInfo(envelop, (X509Certificate[]) ke.getCertificateChain()); } else { throw new IllegalArgumentException( "La estructura para el ContentInfo indicado no esta soportada o no admite multiples remitentes"); //$NON-NLS-1$ } if (newEnvelop == null) { throw new AOException("Error al agregar el nuevo remitente al envoltorio"); //$NON-NLS-1$ } return newEnvelop; } /** Algoritmo de firma que se utilizará internamente en el sobre. El * algoritmo de huella digital se tomará de este. * @param algorithm * Algoritmo de firma. */ public void setSignatureAlgorithm(final String algorithm) { this.signatureAlgorithm = algorithm == null ? AOSignConstants.DEFAULT_SIGN_ALGO : algorithm; } /** Establece la contraseña o clave para la encriptación de los * datos. * @param keyPass * Clave en base 64 o contraseña de cifrado. */ public void setCipherKey(final String keyPass) { this.cipherKey = keyPass; } /** Recupera el algoritmo de firma configurado. El algoritmo de huella * digital se tomará de este. * @return Cadena de texto identificativa para el algoritmo de firma */ String getSignatureAlgorithm() { return this.signatureAlgorithm; } /** Recupera la clave o contrascontraseña para la encriptación * de los datos. * @return Clave en base 64 o contraseña de cifrado. */ String getCipherKey() { return this.cipherKey; } /** Recupera el contenido de un envoltorio CMS. * @param cmsEnvelop Envoltorio CMS. * @param addresseePke Clave privada del destinatario que desea desensobrar. * @return Contenido del envoltorio. * @throws InvalidKeyException Cuando la clave de descifrado configurada no sea válida o pertenezca a un destinatario. * @throws AOException Cuando se produce un error durante al desenvolver los datos. * @throws InvalidKeySpecException Cuando ocurren problemas relacionados con la estructura interna de las claves */ @Override public byte[] recoverData(final byte[] cmsEnvelop, final PrivateKeyEntry addresseePke) throws InvalidKeyException, AOException, IOException, InvalidKeySpecException { final org.bouncycastle.asn1.ASN1InputStream is = new org.bouncycastle.asn1.ASN1InputStream(cmsEnvelop); // Leemos los datos final org.bouncycastle.asn1.ASN1Sequence dsq = (org.bouncycastle.asn1.ASN1Sequence) is.readObject(); is.close(); final Enumeration<?> objects = dsq.getObjects(); // Elementos que contienen los elementos OID Data final org.bouncycastle.asn1.ASN1ObjectIdentifier doi = (org.bouncycastle.asn1.ASN1ObjectIdentifier) objects .nextElement(); byte[] datos; try { if (doi.equals(org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.data)) { Logger.getLogger("es.gob.afirma") //$NON-NLS-1$ .warning("La extraccion de datos de los envoltorios CMS Data no esta implementada"); //$NON-NLS-1$ datos = null; } else if (doi.equals(org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.digestedData)) { Logger.getLogger("es.gob.afirma") //$NON-NLS-1$ .warning("La extraccion de datos de los envoltorios CMS DigestedData no esta implementada"); //$NON-NLS-1$ datos = null; } else if (doi.equals(org.bouncycastle.asn1.cms.CMSObjectIdentifiers.compressedData)) { datos = AOCMSEnveloper.recoverCMSCompressedData(cmsEnvelop); } else if (doi.equals(org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.encryptedData)) { datos = AOCMSEnveloper.recoverCMSEncryptedData(cmsEnvelop, this.cipherKey); } else if (doi.equals(org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.envelopedData)) { datos = AOCMSEnveloper.recoverCMSEnvelopedData(cmsEnvelop, addresseePke); } else if (doi.equals(org.bouncycastle.asn1.cms.CMSObjectIdentifiers.authEnvelopedData)) { datos = AOCMSEnveloper.recoverCMSAuthenticatedEnvelopedData(cmsEnvelop, addresseePke); } else if (doi.equals(org.bouncycastle.asn1.cms.CMSObjectIdentifiers.authenticatedData)) { datos = AOCMSEnveloper.recoverCMSAuthenticatedData(cmsEnvelop, addresseePke); } else if (doi.equals(org.bouncycastle.asn1.cms.CMSObjectIdentifiers.signedAndEnvelopedData)) { datos = AOCMSEnveloper.recoverCMSSignedEnvelopedData(cmsEnvelop, addresseePke); } else { throw new AOInvalidFormatException( "Los datos introducidos no se corresponden con un tipo de objeto CMS soportado"); //$NON-NLS-1$ } } catch (final AOInvalidRecipientException e) { throw new InvalidKeyException( "La clave indicada no pertenece a ninguno de los destinatarios del envoltorio", e); //$NON-NLS-1$ } catch (final CertificateEncodingException e) { throw new AOException("Error al descodificar los certificados del envoltorio", e); //$NON-NLS-1$ } catch (final NoSuchAlgorithmException e) { throw new AOException("No se reconoce el algoritmo indicado", e); //$NON-NLS-1$ } catch (final NoSuchPaddingException e) { throw new AOException("No se reconoce el tipo de relleno indicado", e); //$NON-NLS-1$ } catch (final InvalidAlgorithmParameterException e) { throw new AOException("No se reconoce la configuracion del algoritmo indicado", e); //$NON-NLS-1$ } catch (final IllegalBlockSizeException e) { throw new AOException("Tamano de bloque invalido: " + e, e); //$NON-NLS-1$ } catch (final BadPaddingException e) { throw new AOException("relleno invalido: " + e, e); //$NON-NLS-1$ } return datos; } /** Recupera el contenido de un envoltorio CompressedData. * @param compressedData * Envoltorio CMS de tipo CompressedData. * @return Contenido del envoltorio. * @throws IOException * Cuando ocurre un error al descomprimir los datos. */ static byte[] recoverCMSCompressedData(final byte[] compressedData) throws IOException { return CMSCompressedData.getContentCompressedData(compressedData); } /** Recupera el contenido de un envoltorio EncryptedData. * @param encryptedData * Envoltorio CMS de tipo EncryptedData. * @param passkey * Contraseña o clave (base64) necesaria para desencriptar * los datos. * @return Contenido del envoltorio. * @throws InvalidKeyException * Cuando la clave proporcionada no es válida. * @throws AOException * Cuando se produce un error al desenvolver los datos. * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws NoSuchAlgorithmException Si el JRE no soporta algún algoritmo necesario * @throws IOException En caso de error en la lectura o tratamiento de datos * @throws InvalidKeySpecException Cuando ocurren problemas relacionados con la estructura interna de las claves */ static byte[] recoverCMSEncryptedData(final byte[] encryptedData, final String passkey) throws InvalidKeyException, AOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, IOException { return new CMSDecipherEncryptedData().dechiperEncryptedData(encryptedData, passkey); } /** Recupera el contenido de un envoltorio EnvelopedData. * @param envelopedData * Envoltorio CMS de tipo EnvelopedData. * @param ke * Clave de un destinatario del sobre. * @return Contenido del envoltorio. * @throws IOException * Si ocurre algún problema leyendo o escribiendo los * datos * @throws CertificateEncodingException * Si se produce alguna excepción con los certificados de * firma. * @throws AOException * Cuando ocurre un error durante el proceso de descifrado * (formato o clave incorrecto,...) * @throws AOInvalidRecipientException * Cuando se indica un certificado que no está entre los * destinatarios del sobre. * @throws InvalidKeyException * Cuando la clave almacenada en el sobre no es válida. * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws NoSuchAlgorithmException Si el JRE no soporta algún algoritmo necesario * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo */ static byte[] recoverCMSEnvelopedData(final byte[] envelopedData, final PrivateKeyEntry ke) throws IOException, CertificateEncodingException, AOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { return CMSDecipherEnvelopData.dechiperEnvelopData(envelopedData, ke); } /** Recupera el contenido de un envoltorio SignedEnvelopedData. * @param signedEnvelopedData * Envoltorio CMS de tipo SignedEnvelopedData. * @param ke * Clave de un destinatario del sobre. * @return Contenido del envoltorio. * @throws IOException * Si ocurre algún problema leyendo o escribiendo los * datos * @throws CertificateEncodingException * Si se produce alguna excepción con los certificados de * firma. * @throws AOException * Cuando ocurre un error durante el proceso de descifrado * (formato o clave incorrecto,...) * @throws AOInvalidRecipientException * Cuando se indica un certificado que no está entre los * destinatarios del sobre. * @throws InvalidKeyException * Cuando la clave almacenada en el sobre no es válida. * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws NoSuchAlgorithmException Si el JRE no soporta algún algoritmo necesario * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo */ static byte[] recoverCMSSignedEnvelopedData(final byte[] signedEnvelopedData, final PrivateKeyEntry ke) throws IOException, CertificateEncodingException, AOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { return CMSDecipherSignedAndEnvelopedData.dechiperSignedAndEnvelopData(signedEnvelopedData, ke); } /** Comprueba la integridad de un envoltorio AuthenticatedData y, si es * correcto, extrae su contenido. * @param authenticatedData Envoltorio CMS de tipo AuthenticatedData. * @param ke Clave de un destinatario del sobre. * @return Contenido del envoltorio. * @throws IOException Si ocurre algún problema leyendo o escribiendo los * datos * @throws CertificateEncodingException Si el certificado proporcionado no se adecúa a la * norma X.509v3 * @throws InvalidKeyException Cuando la clave almacenada en el sobre no es válida. * @throws NoSuchAlgorithmException Cuando no se reconoce el algoritmo * utilizado para generar el código de autenticación. * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws AOException Si se produce cualquier otro error durante el proceso */ static byte[] recoverCMSAuthenticatedData(final byte[] authenticatedData, final PrivateKeyEntry ke) throws IOException, CertificateEncodingException, AOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { return new CMSDecipherAuthenticatedData().decipherAuthenticatedData(authenticatedData, ke); } /** Recupera el contenido de un envoltorio AuthenticatedEnvelopedData. * @param authenticatedEnvelopedData * Envoltorio CMS de tipo AuthenticatedEnvelopedData. * @param ke * Clave de un destinatario del sobre. * @return Contenido del envoltorio. * @throws IOException * Si ocurre algun error genérico de entrada/salida * @throws IOException * Si ocurre algún problema leyendo o escribiendo los * datos * @throws CertificateEncodingException * Si se produce alguna excepción con los certificados de * firma. * @throws AOException * Cuando ocurre un error durante el proceso de descifrado * (formato o clave incorrecto,...) * @throws AOInvalidRecipientException * Cuando se indica un certificado que no está entre los * destinatarios del sobre. * @throws InvalidKeyException * Cuando la clave almacenada en el sobre no es válida. * @throws NoSuchPaddingException Si no se soporta algún método de relleno * @throws NoSuchAlgorithmException Si el JRE no soporta algún algoritmo necesario * @throws BadPaddingException Si hay problemas estableciendo el relleno de los datos * @throws IllegalBlockSizeException Si no cuadran los tamaños de bloque de los algoritmos usados * @throws InvalidAlgorithmParameterException Si no se soporta algún parámetro necesario * para algún algoritmo */ static byte[] recoverCMSAuthenticatedEnvelopedData(final byte[] authenticatedEnvelopedData, final PrivateKeyEntry ke) throws IOException, CertificateEncodingException, AOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { return CMSDecipherAuthenticatedEnvelopedData.dechiperAuthenticatedEnvelopedData(authenticatedEnvelopedData, ke); } /** Método que comprueba que unos datos se corresponden con una * estructura CMS/PKCS#7. Se realiza la verificación sobre los los * siguientes tipos reconocidos: * <ul> * <li>Data</li> * <li>Signed Data</li> * <li>Digested Data</li> * <li>Encrypted Data</li> * <li>Enveloped Data</li> * <li>Signed and Enveloped Data</li> * <li>Authenticated Data</li> * <li>Authenticated and Enveloped Data</li> * </ul> * @param cmsData * Datos que deseamos comprobar. * @return La validez del archivo cumpliendo la estructura. */ public static boolean isCMSValid(final byte[] cmsData) { return CMSHelper.isCMSValid(cmsData); } /** Método que comprueba que unos datos se corresponden con una * estructura CMS/PKCS#7 concreta. * @param data * Datos que deseamos comprobar. * @param type * Tipo de contenido del envoltorio que queremos comprobar. * @return Indica los datos son una envoltura CMS con el tipo de contenido * indicado. */ public static boolean isCMSValid(final byte[] data, final String type) { return CMSHelper.isCMSValid(data, type); } }