none
Firmar documento con SHA1withRSA o SHA1withDSA

    Pregunta

  • Buenas tardes amigos,
         tengo el siguiente problema debo conectarme a un web service enviando un xml el cual tiene un tag para colocar la firma digital el cual puede ser SHA1withRSA(Keysize=2048) o SHA1withDSA(Keysize=1024)ambos con formato X.509 v3, por mas que busco solo encuentro como hacer esto en java, alguien me podra guiar o mostrarme un ejemplo de como poder firma el XML con algunos de los dos algoritmo de fima digital.

    Desde ya muchas gracias
    martes, 16 de junio de 2009 20:56

Respuestas

  • Hola Walter,

    Parece ser que el RSACryptoServiceProvider y DSACryptoServiceProvider tan sólo proporcionan servicios de cifrado/descifrado.
    En mi anterior explicación cometí el error de asumir que estos proveedores podrían ser utilizados para generar hashs firmados, por lo que siento la posibles molestias.

    El proceso que tendrás que seguir es:
    - Generar el hash de forma independiente con SHA1CryptoServiceProvider a partir de los datos
    - Firmar con los algoritmos RSA o DSA el hash generado.

    He encontrado un artículo que explica el proceso completo, incluido el proceso de generación de claves.

    http://www.codeproject.com/KB/security/EZRSA.aspx?fid=473703&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2659820

    Por cierto...la forma de transformar la cadena a bytes es un poco peligrosa (asumes que cada carácter ocupa 1 byte)...te recomiendo algo parecido a esto:
    byte[] data = Encoding.UTF8.GetBytes(dato);
    SHA1 sha = new SHA1CryptoServiceProvider();
    byte[] result = sha.ComputeHash(data);
    String resultString = Encoding.UTF8.GetString(result);
    

    Espero que te resulte de utilidad,
    Si este mensaje responde a tu pregunta, márcalo como respuesta correcta o vótalo como útil.
    Sergio Ortiz
    i-Card Software CTO

    View Sergio Ortiz's profile on LinkedIn View Sergio Ortiz's profile on Xing
    lunes, 22 de junio de 2009 11:05
  • La verdad que me costo entender el funcionamiento, la idea es que deberas crear a traves de alguna herramienta gratuita 2 archivos:
    1. Archivo con extension .p12 que es un contenedor de tu clave privada con la cual firmaras y la clave publica que en teoria podrias verificar si esta correctamente firmada (yo no lo uso).
    2. Archivo con extension .cer que le entragaras a la otra persona que contendra la clave publica para que pueda verificar si se trata de tu firma (yo verifico con este mismo si lo firme correctamente).
     
    Por supuesto deberas tener el archivo .cer de la otra persona para poder verificar su firma.
     
     
     

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Security.Cryptography;

    using System.Security.Cryptography.X509Certificates;

     

    namespace Encriptacion

    {

        class SHA1withRSA

        {

            X509Certificate2 _CertificadoPublico;

            X509Certificate2 _CertificadoMio;

     

            /// <summary>

            /// Archivo de certificado .P12 creado por mi

            /// </summary>

            public void CargarCertificadoMio(string pArchivo)

            {

                if (File.Exists(pArchivo))

                    _CertificadoPublico = new X509Certificate2(pArchivo);

            }

            /// <summary>

            /// Archivo de certificado .P12 creado por mi

            /// </summary>

            public void CargarCertificadoMio(X509Certificate2 pX509)

            {

                _CertificadoPublico = pX509;

            }

     

            /// <summary>

            /// Archivo de certificado .cer entregado por la otra persona para verificar la firma

            /// </summary>

            public void CargarCertificadoPublico(string pArchivo, string pClave)

            {

                if (File.Exists(pArchivo))

                    _CertificadoMio = new X509Certificate2(pArchivo, pClave);

            }

            /// <summary>

            /// Archivo de certificado .cer entregado por la otra persona para verificar la firma

            /// </summary>

            public void CargarCertificadoPublico(X509Certificate2 pX509)

            {

                _CertificadoMio = pX509;

            }

     

     

     

            public string FirmarSH1withRSA(string pDato)

            {

                RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)_CertificadoMio.PrivateKey;

                SHA1CryptoServiceProvider hasher = new SHA1CryptoServiceProvider();

                byte[] bytesFirmados = RSA.SignData(System.Text.Encoding.UTF8.GetBytes(pDato), hasher);

                return Convert.ToBase64String(bytesFirmados);

            }

     

            public bool VerificarFirmaSH1withRSA(string pTexto, string pFirma)

            {

                byte[] bytesTexto = System.Text.Encoding.UTF8.GetBytes(pTexto);

                byte[] bytesFirmados = Convert.FromBase64String(pFirma);

     

                RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)_CertificadoPublico.PublicKey.Key;

                SHA1CryptoServiceProvider hasher = new SHA1CryptoServiceProvider();

                return RSA.VerifyData(bytesTexto, hasher, bytesFirmados);

            }

        }

    }

     

     

    Espero que les sea de ayuda.


    Me gustaría cambiar el mundo..., pero no me dan el código fuente
    lunes, 02 de agosto de 2010 21:18

Todas las respuestas

  • Hola Walter,

    Puedes utilizar las siguientes funciones del framework...
    Te paso unos enlaces:

    http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1.aspx (Idea general de cómo hacerlo)



    byte[] data = new byte[DATA_SIZE];
    byte[] result; 
    
    SHA1 sha = new SHA1CryptoServiceProvider(); 
    // This is one implementation of the abstract class SHA1.
    result = sha.ComputeHash(data);


    Como observas, SHA1CryptoServiceProvider proporciona la implementación del algoritmo. En tu caso, tendrás que usar RSA(Keysize:2048) o DSA(Keysize:1024)

    Para el primer caso, puedes usar el RSACryptoServiceProvider con el constructor en el que fijarás el tamaño de tu clave.

    http://msdn.microsoft.com/es-es/library/system.security.cryptography.rsacryptoserviceprovider(VS.80).aspx (Clase)
    http://msdn.microsoft.com/es-es/library/zseyf239(VS.80).aspx (Constructor en el que le puedes pasar el Keysize)

    Así, en tu caso el código quedará de la siguente forma.

    byte[] data = new byte[DATA_SIZE];
    byte[] result; 
    
    SHA1 sha = new RSACryptoServiceProvider(2048); 
    result = sha.ComputeHash(data);
    Análogamente para DSA...puedes usar el DSACryptoServiceProvider.

    http://msdn.microsoft.com/es-es/library/system.security.cryptography.dsacryptoserviceprovider.aspx (Clase)
    http://msdn.microsoft.com/es-es/library/w8898ktb.aspx (Constructor en el que le puedes pasar el Keysize)

    Espero que te resulte de utilidad,
    Si este mensaje responde a tu pregunta, márcalo como respuesta correcta o vótalo como útil.
    Sergio Ortiz
    i-Card Software CTO

    View Sergio Ortiz's profile on LinkedIn View Sergio Ortiz's profile on Xing
    miércoles, 17 de junio de 2009 18:00
  • Gracias Sergio, intente implementarlo de la siguiente manera:
    private string ObtenerSH1withRSA_2048(string Dato)
            {
                byte[] data = new byte[Dato.Length];
                for (int i = 0; i < Dato.Length; i++)
                    data[i] = (byte)Dato[i];
                byte[] result;
                SHA1 sha = new RSACryptoServiceProvider(2048);
                result = sha.ComputeHash(data);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < result.Length; i++) sb.AppendFormat("{0:x2}", result[i]);
                return sb.ToString();
            }
    
    pero me tira el siguiente error "Error    1    No se puede convertir implícitamente el tipo 'System.Security.Cryptography.RSACryptoServiceProvider' a 'System.Security.Cryptography.SHA1'    C:\Fuente\prueba.cs    238    24    Prueba"

    también se me presenta las siguientes dudas:
    1. ¿como genero mi clave publica y privada?
    2. ¿Como tomo la clave publica de un cliente y verifico la firma digital de los datos que llegan?
    3. ¿En el código de arriba en el caso que me haya faltado algo, como lo firmo con mi clave privada?
    saludos,

    Walter Loose
    viernes, 19 de junio de 2009 19:54
  • Hola Walter,

    Parece ser que el RSACryptoServiceProvider y DSACryptoServiceProvider tan sólo proporcionan servicios de cifrado/descifrado.
    En mi anterior explicación cometí el error de asumir que estos proveedores podrían ser utilizados para generar hashs firmados, por lo que siento la posibles molestias.

    El proceso que tendrás que seguir es:
    - Generar el hash de forma independiente con SHA1CryptoServiceProvider a partir de los datos
    - Firmar con los algoritmos RSA o DSA el hash generado.

    He encontrado un artículo que explica el proceso completo, incluido el proceso de generación de claves.

    http://www.codeproject.com/KB/security/EZRSA.aspx?fid=473703&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2659820

    Por cierto...la forma de transformar la cadena a bytes es un poco peligrosa (asumes que cada carácter ocupa 1 byte)...te recomiendo algo parecido a esto:
    byte[] data = Encoding.UTF8.GetBytes(dato);
    SHA1 sha = new SHA1CryptoServiceProvider();
    byte[] result = sha.ComputeHash(data);
    String resultString = Encoding.UTF8.GetString(result);
    

    Espero que te resulte de utilidad,
    Si este mensaje responde a tu pregunta, márcalo como respuesta correcta o vótalo como útil.
    Sergio Ortiz
    i-Card Software CTO

    View Sergio Ortiz's profile on LinkedIn View Sergio Ortiz's profile on Xing
    lunes, 22 de junio de 2009 11:05
  • Hola Sergio,
          Te agradezco por la grana ayuda que me prestaste, espero que alguna ves pueda devolverte el favor.

    Muchas gracias!!!

    Saludos
    Walter Loose
    lunes, 22 de junio de 2009 12:46
  • Es un placer :)
    Si este mensaje responde a tu pregunta, márcalo como respuesta correcta o vótalo como útil.
    Sergio Ortiz
    i-Card Software CTO

    View Sergio Ortiz's profile on LinkedIn View Sergio Ortiz's profile on Xing
    lunes, 22 de junio de 2009 17:13
  • La verdad que me costo entender el funcionamiento, la idea es que deberas crear a traves de alguna herramienta gratuita 2 archivos:
    1. Archivo con extension .p12 que es un contenedor de tu clave privada con la cual firmaras y la clave publica que en teoria podrias verificar si esta correctamente firmada (yo no lo uso).
    2. Archivo con extension .cer que le entragaras a la otra persona que contendra la clave publica para que pueda verificar si se trata de tu firma (yo verifico con este mismo si lo firme correctamente).
     
    Por supuesto deberas tener el archivo .cer de la otra persona para poder verificar su firma.
     
     
     

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Security.Cryptography;

    using System.Security.Cryptography.X509Certificates;

     

    namespace Encriptacion

    {

        class SHA1withRSA

        {

            X509Certificate2 _CertificadoPublico;

            X509Certificate2 _CertificadoMio;

     

            /// <summary>

            /// Archivo de certificado .P12 creado por mi

            /// </summary>

            public void CargarCertificadoMio(string pArchivo)

            {

                if (File.Exists(pArchivo))

                    _CertificadoPublico = new X509Certificate2(pArchivo);

            }

            /// <summary>

            /// Archivo de certificado .P12 creado por mi

            /// </summary>

            public void CargarCertificadoMio(X509Certificate2 pX509)

            {

                _CertificadoPublico = pX509;

            }

     

            /// <summary>

            /// Archivo de certificado .cer entregado por la otra persona para verificar la firma

            /// </summary>

            public void CargarCertificadoPublico(string pArchivo, string pClave)

            {

                if (File.Exists(pArchivo))

                    _CertificadoMio = new X509Certificate2(pArchivo, pClave);

            }

            /// <summary>

            /// Archivo de certificado .cer entregado por la otra persona para verificar la firma

            /// </summary>

            public void CargarCertificadoPublico(X509Certificate2 pX509)

            {

                _CertificadoMio = pX509;

            }

     

     

     

            public string FirmarSH1withRSA(string pDato)

            {

                RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)_CertificadoMio.PrivateKey;

                SHA1CryptoServiceProvider hasher = new SHA1CryptoServiceProvider();

                byte[] bytesFirmados = RSA.SignData(System.Text.Encoding.UTF8.GetBytes(pDato), hasher);

                return Convert.ToBase64String(bytesFirmados);

            }

     

            public bool VerificarFirmaSH1withRSA(string pTexto, string pFirma)

            {

                byte[] bytesTexto = System.Text.Encoding.UTF8.GetBytes(pTexto);

                byte[] bytesFirmados = Convert.FromBase64String(pFirma);

     

                RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)_CertificadoPublico.PublicKey.Key;

                SHA1CryptoServiceProvider hasher = new SHA1CryptoServiceProvider();

                return RSA.VerifyData(bytesTexto, hasher, bytesFirmados);

            }

        }

    }

     

     

    Espero que les sea de ayuda.


    Me gustaría cambiar el mundo..., pero no me dan el código fuente
    lunes, 02 de agosto de 2010 21:18
  • Hola que tal, oye tengo una pregunta, el archivo .p12 cómo lo conseguiste? en base a qué? Según yo transformaste el archivo .key de la llave privada, pero me gustaría saber cómo es que lo transformaste.

    Gracias.

    martes, 07 de septiembre de 2010 14:21
  • Estimado, quizas esto pueda ayudarlo

    http://lenguajedemaquinas.blogspot.com/2013/05/ejemplo-timbre-electronico-del-dte.html

    viernes, 12 de julio de 2013 15:15