public static byte[] generateSignedData( P7ContentSignerParameters parameters, bool omitContent, AdESPolicy policy, bool signingCertificateV2, X509Certificate2 keyEntry, byte[] messageDigest, bool padesMode, String contentType, String contentDescription) { if (parameters == null) { throw new ArgumentNullException("Los parametros no pueden ser nulos"); } String signatureAlgorithm = parameters.GetSignatureAlgorithm(); X509Certificate2[] signerCertificateChain = parameters.GetSignerCertificateChain(); DateTime signDate = DateTime.Now; // Ya que el contenido de la firma puede ser grande, lo obtenemos solo al principio byte[] content = parameters.GetContent(); byte[] preSignature = CAdESTriPhaseSigner.PreSign( AOSignConstants.GetDigestAlgorithmName(signatureAlgorithm), (omitContent) ? null : content, signerCertificateChain, policy, signingCertificateV2, (messageDigest == null && content != null) ? Digester.Digest(content, AOSignConstants.GetDigestAlgorithmName(signatureAlgorithm)) : messageDigest, signDate, padesMode, contentType, contentDescription ); byte[] signature = new AOPkcs1Signer().sign(preSignature, signatureAlgorithm, keyEntry); return CAdESTriPhaseSigner.PostSign( AOSignConstants.GetDigestAlgorithmName(signatureAlgorithm), (omitContent) ? null : content, signerCertificateChain, signature, // Volvemos a crear la prefirma simulando una firma trifasica en la que la postfirma no cuenta con el // resultado de la prefirma CAdESTriPhaseSigner.PreSign( AOSignConstants.GetDigestAlgorithmName(signatureAlgorithm), (omitContent) ? null : content, signerCertificateChain, policy, signingCertificateV2, (messageDigest == null && content != null) ? Digester.Digest(content, AOSignConstants.GetDigestAlgorithmName(signatureAlgorithm)) : messageDigest, signDate, padesMode, contentType, contentDescription ) ); }
/** Firma datos en formato CAdES.<br/> * @param data Datos que deseamos firmar. * @param algorithm Algoritmo a usar para la firma. * <p>Se aceptan los siguientes algoritmos en el parámetro <code>algorithm</code>:</p> * <ul> * <li> <i>SHA1withRSA</i></li> * <li> <i>MD5withRSA</i> (no recomendado por vulnerable)</li> * <li> <i>MD2withRSA</i> (no recomendado por vulnerable)</li> * <li> <i>SHA256withRSA</i></li> * <li> <i>SHA384withRSA</i></li> * <li> <i>SHA512withRSA</i></li> * </ul> * @param keyEntry Entrada que apunta a la clave privada a usar para firmar * @param xParams Parámetros adicionales para la firma. * <p>Se aceptan los siguientes valores en el parámetro <code>xParams</code>:</p> * <dl> * <dt><b><i>includeOnlySignningCertificate</i></b></dt> * <dd> * Si se establece a {@code true} se incluye en la firma únicamente el certificado del firmante (y no la cadena de certificación completa). * Si no se establece o se establece a o {@code false} se incluirá toda la cadena de certificación. * </dd> * <dt><b><i>mode</i></b></dt> * <dd> * Modo de firma a usar. El valor <code>explicit</code> indica que no se incluyen los datos firmados, sino una * referencia a estos, mientras que el valor <code>implicit</code> indica que sí se incluirán dentro de * la propia firma los datos firmados * </dd> * <dt><b><i>policyIdentifier</i></b></dt> * <dd> * Identificador de la política de firma. Debe ser un OID (o una URN de tipo OID) que identifique * únivocamente la política en formato ASN.1 procesable. * </dd> * <dt><b><i>policyIdentifierHash</i></b></dt> * <dd> * Huella digital del documento de política de firma (normalmente del mismo fichero en formato ASN.1 procesable). * Si no se indica una huella digital y el parámetro <code>policyIdentifier</code> no es una URL accesible * universalmente se usará <code>0</code>, mientras que si no se indica una huella digital pero el parámetro * <code>policyIdentifier</code> es una URL accesible universalmente, se descargara el fichero apuntado por la URL para calcular la huella * digital <i>al vuelo</i>. * </dd> * <dt><b><i>policyIdentifierHashAlgorithm</i></b></dt> * <dd> * Algoritmo usado para el cálculo de la huella digital indicada en el parámetro <code>policyIdentifierHash</code>. * Es obligario indicarlo cuando se proporciona una huella digital distinta de <code>0</code>. * </dd> * <dt><b><i>policyQualifier</i></b></dt> * <dd> * URL que apunta al documento descriptivo de la política de firma (normalmente un documento PDF con una descripción textual). * </dd> * <dt><b><i>precalculatedHashAlgorithm</i></b></dt> * <dd> * Algoritmo de huella digital (a usar para la firma) cuando esta se proporciona precalculada. Cuando se usan modos de firma * <i>explícitos</i>, en los que los datos no se incluyen en la firma, es posible trabajar sin proporcionarlos, indicando * únicamente su huella digital en el parámetro <code>data</code> y el algoritmo usado para su cálculo.<br> * <b> * Siempre que se de valor a este parámetro se supondrá que los datos proporcionados en el parámetro * <code>data</code> son la huella digital de los datos a firmar, y no los datos a firmar en si. * </b> * </dd> * <dt><b><i>signingCertificateV2</i></b></dt> * <dd> * Debe establecerse a <code>true</code> si se desea usar la versión 2 del atributo * <i>Signing Certificate</i> de CAdES. Si no se establece un valor para este parámetro * se utilizaráa la versión 1 con las firmas realizadas con algoritmos SHA1 y * la versión 2 con las firmas realizadas con cualquier otro algoritmo. * </dd> * </dl> * @return Firma en formato CAdES * @throws AOException Cuando ocurre cualquier problema durante el proceso */ public byte[] sign(byte[] data, String algorithm, X509Certificate2[] keyEntry, Dictionary<string,string> xParams) { //Aunque está implementado, omitimos el checkeo de BC. Razon: mirar dentro de la clase BCChecker(). //new BCChecker().checkBouncyCastle(); Dictionary<string,string> extraParams = xParams != null ? xParams : new Dictionary<string,string>(); string precalculatedDigest = null; extraParams.TryGetValue("precalculatedHashAlgorithm", out precalculatedDigest); byte[] messageDigest = null; if (precalculatedDigest != null) { messageDigest = data; } bool signingCertificateV2 = false; if (AOSignConstants.isSHA2SignatureAlgorithm(algorithm)) { signingCertificateV2 = true; } else if (extraParams.ContainsKey("signingCertificateV2")) { string signing = null; extraParams.TryGetValue("signingCertificateV2", out signing); if(signing!=null) signingCertificateV2 = Boolean.Parse(signing); } else { signingCertificateV2 = !"SHA1".Equals(AOSignConstants.GetDigestAlgorithmName(algorithm)); } string mode = AOSignConstants.DEFAULT_SIGN_MODE; extraParams.TryGetValue("mode", out mode); //string includeOnlySignningCertificate = null; //extraParams.TryGetValue("includeOnlySignningCertificate", out includeOnlySignningCertificate); //if(includeOnlySignningCertificate!= null){ // bool include = Boolean.Parse(includeOnlySignningCertificate); // if(include){ // } //} P7ContentSignerParameters csp = new P7ContentSignerParameters( data, algorithm, keyEntry ); try { bool omitContent = false; if (mode.Equals(AOSignConstants.SIGN_MODE_EXPLICIT) || precalculatedDigest != null) { omitContent = true; } String contentTypeOid = AOSignConstants.DEFAULT_CONTENT_OID_DATA; String contentDescription = AOSignConstants.DEFAULT_CONTENT_DESCRIPTION; // DE MOMENTO NO VAMOS A CALCULAR EL MIMETYPE. MANTENDREMOS SIEMPRE POR DEFECTO LOS MISMOS //if (data != null) { // try { // MimeHelper mimeHelper = new MimeHelper(data); // contentDescription = mimeHelper.getDescription(); // contentTypeOid = MimeHelper.transformMimeTypeToOid(mimeHelper.getMimeType()); // } catch (Exception e) { // Console.WriteLine("No se han podido cargar las librerias para identificar el tipo de dato firmado: " + e); // } //} bool padesMode = false; string sPadesMode = null; extraParams.TryGetValue("padesMode", out sPadesMode); if(sPadesMode!=null){ padesMode = Boolean.Parse(sPadesMode); } return GenCAdESEPESSignedData.generateSignedData( csp, omitContent, new AdESPolicy(extraParams), signingCertificateV2, keyEntry[0], //cogemos el elemento 0, que es el que contiene el certificado raiz messageDigest, padesMode, contentTypeOid, contentDescription ); } catch (Exception e) { throw new Exception("Error generando la firma CAdES: " + e, e); } }