Imagen

DESCARGA SOFTWARE PARA FACTURA ELECTRONICA DE AQUI.
Facturacion, Validacion, Addendas, Librerias de programacion, etc.


ECODEX TIENE ESTOS NUEVOS DATOS DE CONTACTO :
Comercializacion y Ventas - Evelia Vicke evicke@ecodex.com.mx 33-16-03-03-48
Soporte - Humberto Guerrero soporte@ecodex.com.mx 33-34-90-46-03

Sello Digital con C#.net

Es tan comun este tema que he decidido abrir un foro especial para este caso. Se trata de programadores que tienen problemas para crear el Sello Digital y que no pasan la validacion
H_info
Mensajes: 3
Registrado: Lun Ene 31, 2011 1:18 pm

Sello Digital con C#.net

Mensajepor H_info » Lun Ene 31, 2011 5:15 pm

Muy buenas tardes, he estado revisando el Blog y me parece un aporte muy bueno de hecho la información que he encontrado me parece muy buena, los felicito.

Te comento que en mi caso hice una aplicación con C#.net (no con Visual Studio si no con un IDE gratuito llamado #develop) para los CFD, esto fue a mediados de diciembre y solo hice una sola factura y la cancele, en este mes llevo ya 100 facturas de las cuales un cliente me regreso una por que el sellado le marcaba invalido en el validador de SAT, en tu validador me da lo mismo (todo correcto menos el sellado), en este caso al empezar a revisar me doy cuenta de que el resultado de la digestion en MD5 para la factura del año pasado no corresponde con con el resultado de la digestion de tu software, y aun que por lo que he leido tu programas en Delphi, me gustaría saber si alguien le ha pasado algo similar con respecto a la digestion MD5?.

En mi caso solo utilizo las librerias de .net para criptografia (using System.Security.Cryptography;), les anexo mi codigo por si quieren verificar la digestion MD5

private static string getMd5Hash(string input)
{
// Se crea un anueva instancia de MD5CryptoServiceProvider
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();

// Se convierte el string a un arreglo de bytes y calcula el hash
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));

// Se crea un nuevo Stringbuilder para almacenar los bytes(se crea un nuevo string)
StringBuilder sBuilder = new StringBuilder();

// se hace un ciclo a travez de cada byte del dato hash
// y le da el formato de hexadecimales de tipo string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}

// por último recupera el string
return sBuilder.ToString();
}

Muchas gracias por sus comentarion y pistas.

Avatar de Usuario
Dado
Mensajes: 15842
Registrado: Mar Jul 06, 2010 7:56 pm

Re: Sello Digital con C#.net

Mensajepor Dado » Lun Ene 31, 2011 6:24 pm

Para este 2011 ya debes cambiar el hash.

Ahora debes usar SHA1, talvez ahi este todo el merequetengue.

(busca SHA1 aqui en el foro, en su momento se discutio mucho al respecto)
ADDENDAS? VALIDACION? CODIGO PARA PROGRAMAR TU PROPIA SOLUCION? TODO LO TENEMOS EN WWW.VALIDACFD.COM VISITANOS !!

Avatar de Usuario
acanas
Mensajes: 477
Registrado: Mar Ene 11, 2011 3:18 pm

Re: Sello Digital con C#.net

Mensajepor acanas » Lun Ene 31, 2011 6:48 pm

// Se convierte el string a un arreglo de bytes y calcula el hash
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));


Veo un grave error en tu codificación ya que no estas tomando en cuenta el encoding en UTF8 en la cadena al convertirla a un arreglo byte. Así deberias tener tu hash en MD5 y SHA1:

(<=2010)
MD5:

Código: Seleccionar todo


private static string GetMD5(string text)
        {
            byte[] hashValue;
            byte[] message = Encoding.UTF8.GetBytes(text);

            MD5 hashString = new MD5CryptoServiceProvider();
            string hex = "";

            hashValue = hashString.ComputeHash(message);
            foreach (byte x in hashValue)
            {
                hex += String.Format("{0:x2}", x);
            }
            return hex;
        }


(>=2011)
SHA1:

Código: Seleccionar todo


 private static string GetSHA1(string text)
        {
            byte[] hashValue;
            byte[] message = Encoding.UTF8.GetBytes(text);

            SHA1Managed hashString = new SHA1Managed();
            string hex = "";

            hashValue = hashString.ComputeHash(message);
            foreach (byte x in hashValue)
            {
                hex += String.Format("{0:x2}", x);
            }
            return hex;
        }

Zyphersoft Development

H_info
Mensajes: 3
Registrado: Lun Ene 31, 2011 1:18 pm

Re: Sello Digital con C#.net

Mensajepor H_info » Mar Feb 01, 2011 12:37 pm

Muchas gracias acanas, omitia el paso de convertir a UTF8 y daba por hecho que por almacenarlo en un archivo txt, con formato UTF8 era suficinete, graias por tu ayuda.

En este momento la digestion con MD5 y SAH-1 me da equivalente al ejemplo del post "Generacion del sello paso a paso", solo que el resultado final del sellado no es igual que el del ejemplo, y tengo un par de dudas:

1.- La utilizacion de la llave privada con C# la realizo de esta manera:

Código: Seleccionar todo

 public static void GetKeyFromContainer(string ContainerName)
       {
           // Create the CspParameters object and set the key container
           // name used to store the RSA key pair.
           CspParameters cp = new CspParameters();
           cp.KeyContainerName = ContainerName;
   
           // Create a new instance of RSACryptoServiceProvider that accesses
           // the key container MyKeyContainerName.
           RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
   
           // Display the key information to the console.
           //MessageBox.Show("Key retrieved from container : \n {0}", rsa.ToXmlString(true));
          
          
           string xmlKey = rsa.ToXmlString(true);

            // Si no existe el directorio, crearlo
            string dirPruebas = Path.GetDirectoryName(ficPruebas);

            if(Directory.Exists(dirPruebas) == false)
            {
                Directory.CreateDirectory(dirPruebas);
            }

            using(StreamWriter sw = new StreamWriter(ficPruebas, false, Encoding.UTF8))
            {
                sw.WriteLine(xmlKey);
                sw.Close();
            }
          
       }


así pue el resultado es un XML de la llave privada, Cuando la comparo con el ejemplo que esta publicado "Generacion de Sello Digital paso a paso" no es equivalente, ¿conoces algúm método del servicio criptoprovider que de el mismo resultado?, o ¿es que en C# se tiene que utilizar deestra manera para poder hacer el firmado?

y la segunda.

2.- Una vez con la cadena en SHA-1 y llaveprivada en xml proceso a la encriptaicon RSA, pero el resultado no es el mismo que aparece en el sello del ejemplo que está publicado en "GENERACION de sello digital paso a paso", anexo mi codigo y agradezco sus comentarios, gracias.

Código: Seleccionar todo



//////////////////////////////////////////////////////////////////////////////////
            // SE RECUPERA LA LLAVE PRIVADA Y SE PREPARA PARA FIMAR CON RSA //////////////////
            //////////////////////////////////////////////////////////////////////////////////
            //primero la talacha de .key a mxl
       GetKeyFromContainer(textBox2.Text);   //Es el método de arriba
           // Si no existe el archivo de claves
            if(File.Exists(ficPruebas) == false)
            {
               MessageBox.Show("Te falta la Llave");
               crearXMLclaves(ficPruebas);
            }
            //Se recupera la clave apartir del XML
            string xmlKeys = clavesXML(ficPruebas);
           
            //////////////////////////////////////////////////////////////////////////////////
            // SE FIMAR CON RSA //////////////////
            //////////////////////////////////////////////////////////////////////////////////
              //Apartir de aca va el cifrado RSA
             RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
          rsa.FromXmlString(xmlKeys);
          byte[] datos = rsa.Encrypt(Encoding.Default.GetBytes(richTextBox3.Text), false);
         
                     
             //Ahora se pasan los datos a base64
          try {
               base64String = System.Convert.ToBase64String(datos, 0, datos.Length);
               //MessageBox.Show("Y el sello digital EstructuraFactura:  " + base64String);
              }
              catch (System.ArgumentNullException) {
               MessageBox.Show("El arreglo binario es nulo.");
               base64String = "0";
         }
            richTextBox4.Text =  base64String;




Gracias por su ayuda.

H_info
Mensajes: 3
Registrado: Lun Ene 31, 2011 1:18 pm

Re: Sello Digital con C#.net

Mensajepor H_info » Mar Feb 01, 2011 3:58 pm

Gracias por el tip acanas, mi digestion estaba incorrecta, sin embargo aun no tengo el resultado esperado en el sello digital, tengo duda en dos partes de mi código una es en la utilizacion de la llave privada ya que en C# lo hago recuperando la llave privada como un xml (abajo les muestro mi codigo).

Código: Seleccionar todo


 public static void GetKeyFromContainer(string ContainerName)
       {
           // Create the CspParameters object and set the key container
           // name used to store the RSA key pair.
           CspParameters cp = new CspParameters();
           cp.KeyContainerName = ContainerName;
   
           // Create a new instance of RSACryptoServiceProvider that accesses
           // the key container MyKeyContainerName.
           RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
   
           // Display the key information to the console.
           //MessageBox.Show("Key retrieved from container : \n {0}", rsa.ToXmlString(true));
          
          
           string xmlKey = rsa.ToXmlString(true);

            // Si no existe el directorio, crearlo
            string dirPruebas = Path.GetDirectoryName(ficPruebas);

            if(Directory.Exists(dirPruebas) == false)
            {
                Directory.CreateDirectory(dirPruebas);
            }

            using(StreamWriter sw = new StreamWriter(ficPruebas, false, Encoding.UTF8))
            {
                sw.WriteLine(xmlKey);
                sw.Close();
            }
          
       }


Y posteriormente se realiza el encriptamiento con RSA, para lo cual utilizo esta otra parte de mi código.

Código: Seleccionar todo


  //////////////////////////////////////////////////////////////////////////////////
            // SE RECUPERA LA LLAVE PRIVADA Y SE PREPARA PARA FIMAR CON RSA //////////////////
            //////////////////////////////////////////////////////////////////////////////////
            //primero la talacha de .key a mxl
          GetKeyFromContainer(textBox2.Text);
           // Si no existe el fichero de claves
            if(File.Exists(ficPruebas) == false)
            {
               MessageBox.Show("Te falta la Llave");
               crearXMLclaves(ficPruebas);
            }
            //Se recupera la clave apartir del XML
            string xmlKeys = clavesXML(ficPruebas);
           
            //////////////////////////////////////////////////////////////////////////////////
            // SE FIMAR CON RSA //////////////////
            //////////////////////////////////////////////////////////////////////////////////
              //Apartir de aca va el cifrado RSA
             RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
          rsa.FromXmlString(xmlKeys);
          //byte[] datos = rsa.Encrypt(Encoding.Default.GetBytes(richTextBox3.Text), false);
          byte[] datos = rsa.SignHash(Encoding.Default.GetBytes(hex),xmlKeys);  //
                     
             //Ahora se pasan los datos a base64
          try {
               base64String = System.Convert.ToBase64String(datos, 0, datos.Length);
               //MessageBox.Show("Y el sello digital EstructuraFactura:  " + base64String);
              }
              catch (System.ArgumentNullException) {
               MessageBox.Show("El arreglo binario es nulo.");
               base64String = "0";
         }
            richTextBox4.Text =  base64String;


La salida es muy parecida, sin embargo no es el resultado deseado, agradezco todos los comentarios que me hagan llegar.

Raym0n
Mensajes: 7
Registrado: Lun Ene 03, 2011 8:03 pm

Re: Sello Digital con C#.net

Mensajepor Raym0n » Mar May 03, 2011 3:12 pm

Hola, he estado buscando como hacer justamente eso.... tubo fin este post o hasta hay se quedo???

Avatar de Usuario
acanas
Mensajes: 477
Registrado: Mar Ene 11, 2011 3:18 pm

Re: Sello Digital con C#.net

Mensajepor acanas » Mar May 03, 2011 10:30 pm

uhh nunca vi ese post de vuelta, creo que quedo sepultado entre tantos posts. Fijate que yo utilizo esta libreria para el firmado de mis CFD's.

CryptoSYS PKI TOOLKIT:
http://www.cryptosys.net/pki/index.html
La recomiendo ampliamente.

Features

Provides over 100 core functions to provide PKI cryptography and utilities
Includes detailed 400-page manual
Interfaces for VB6/VBA, C/C++, VB.NET/VB2005/8/x, C# and other languages
Create Cryptographic Message Syntax (CMS, PKCS#7) objects suitable to use in S/MIME messages
Create and manage X.509 certificates
Create and check X.509 certificate revocation lists (CRLs)
Make and read OSCP requests and responses
Make PKCS#10 certificate request files
Provides RSA public key encryption and signing
Generate and manage RSA public and private keys
Carry out "raw" RSA encryption and decryption
Encrypt key data for transport using the PKCS#1 algorithm (v1.5 and OEAP)
Encrypt with symmetrical block ciphers Triple-DES and AES-128/192/256 in 5 standard modes
Generate message digests (hash values) using SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 and MD5
Generate HMAC keyed hash authentication codes
Generate secure random numbers
Convert data to and from base64- and hexadecimal-encoded format
Totally thread-safe.
Runs on any Win32 operating system: 95/98/NT4/2K/XP/2003/Vista/W7. X64 version included.
Independent of Microsoft Cryptographic API (CRAPi).
Does not use COM or Active-X or require registering with RegSvr32 to use.
A Linux Version is available separately.
Automatic self-checking of software integrity and key functions on start up.
Zyphersoft Development

Raym0n
Mensajes: 7
Registrado: Lun Ene 03, 2011 8:03 pm

Re: Sello Digital con C#.net

Mensajepor Raym0n » Mié May 04, 2011 1:08 pm

sobres, gracias acanas, le echare un ojo

altw1zard
Mensajes: 8
Registrado: Dom Ene 30, 2011 9:26 pm

Re: Sello Digital con C#.net

Mensajepor altw1zard » Jue May 05, 2011 12:56 pm

para la obtención del sello utilice este procedimiento de vb.net, partiendo de tener la llave privada como xml y enviando la cadena original como parametros.

ojala y a alguien le sea de ayuda


Código: Seleccionar todo



Private Function GetSello(ByVal XMLKey As String,ByVal CadenaOriginal As String) As String
    Dim cad() As Byte
    Dim Firma() As Byte   
    Dim rsa As System.Security.Cryptography.RSACryptoServiceProvider
    Dim enc As New System.Text.UTF8Encoding(False)
    Dim sha1 As New System.Security.Cryptography.SHA1CryptoServiceProvider
    Try
         
          rsa.FromXmlString(XMLKey)
          cad=enc.GetBytes(CadenaOriginal)
          Firma=rsa.SignData(cad,sha1)
          Return Convert.ToBase64String(Firma)   

    Catch ex As Exception
         Throw Ex
    End Try

End Function



Raym0n
Mensajes: 7
Registrado: Lun Ene 03, 2011 8:03 pm

Re: Sello Digital con C#.net

Mensajepor Raym0n » Jue May 05, 2011 3:21 pm

Es de mucha ayuda, gracias, lo unico que me falta es leer el archivo private key y hacerlo .pem, acanas me compartio un link donde para ver como hacerlo, solo que me lo pidieron los menos costos que se pueda :P, asi que me estoy dando un tiro en inter haber si encuentro algo mas free jejej, en fin, encontre una libreria pero todabia no encuentro bien como funciona, es de www.bouncycastle.org, estoy viendo como hacerle con este, ya solo falta esto y listo gracias por el firmado.


Volver a “SELLO DIGITAL INVALIDO”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 8 invitados