Como validar "a mano" un sello digital

La libreria OpenSSL es la mas usada para generar el sello digital, independientemente del lenguaje aqui encontraras informacion de como usar la libreria
[[ FORO CERRADO DEBIDO A QUE YA LA INFORMACION YA NO ES VIGENTE ]]
danfred
Mensajes: 4
Registrado: Vie Feb 25, 2011 12:03 pm

Re: Como validar "a mano" un sello digital

Mensajepor danfred » Vie Feb 25, 2011 12:18 pm

Buenas

Estoy haciendo un validador que va a leer el CFD en formato XML, pero ando batallando en el utimo paso, el detalle es que no quiero utilizar openssl.exe lo quiero hacer completamente en c# (Visual Studio 2010), aqui les anexo el codigo que me 'genera' el sello digital completo en c# (no ocupa openssl.exe) y ya esta validado por el validador del SAT, a ver quien me echa la mano con el validador en c# de un XML que si contenga el certificado. Gracias

public byte[] hash_sha1_byte(byte[] Value)
{
System.Security.Cryptography.SHA1CryptoServiceProvider x =
new System.Security.Cryptography.SHA1CryptoServiceProvider();
byte[] data = x.ComputeHash(Value);
return data;
}

public string byte_to_string( byte[] data)
{
string ret = "";
for (int i = 0; i < data.Length; i++)
ret += data[i].ToString("x2").ToUpper();
return ret;
}

public string hash_sha1(string Value)
{
byte[] data = hash_sha1_byte(System.Text.Encoding.UTF8.GetBytes(Value));
return byte_to_string(data);
}


public string SelloDigital2(string _rutap12, string _passp12, string cadena)
{
try
{
// uso un archivo xxxx.P12 que incluye todo CERTIFICADO y LLAVES PUBLICAS Y PRIVADAS y _passp12 es el pasword de la PRIVATE KEY
X509Certificate2 certificado = new X509Certificate2( _rutap12, _passp12);
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificado.PrivateKey;
if (rsa == null)
{
throw new Exception("El certificado " + _rutap12 + " no es válido o su contraseña");
}

rsa.PersistKeyInCsp = false;

byte[] data = System.Text.Encoding.UTF8.GetBytes(cadena);
string hash_name;
hash_name = CryptoConfig.MapNameToOID("SHA1");
// Hash the data
data = hash_sha1_byte(data);
// Sign the hash
byte[] encriptado = rsa.SignHash(data, hash_name);
rsa.Clear();
return Convert.ToBase64String(encriptado);
}
catch (Exception ex)
{
return "Error al generar el sello digital " + ex.ToString();
}
}

danfred
Mensajes: 4
Registrado: Vie Feb 25, 2011 12:03 pm

Re: Como validar "a mano" un sello digital

Mensajepor danfred » Vie Feb 25, 2011 12:24 pm

De acuerdo al post anterior esta funcion deberia de funcionar correctamente, pero no jala, ¿alguna idea del porque?, todo indica que la llave publica que se lee, es incorrecta, del archivo xxxx..P12 (ejemplo anterior) obtengo que la llave publica mide 162 bytes, pero los ejemplos que he visto esta llave mide 128 bytes, aunque la clase X509Certificate2 siempre marca 1024 en su elemento keysize.

public string ValidaSelloDigital2(string selloDigital, string cert, string cadena)
{
try
{
byte[] sello_byte = Convert.FromBase64String( selloDigital);
byte[] cert_byte = Convert.FromBase64String( cert);

X509Certificate2 certificado = new X509Certificate2( cert_byte);
//initialze the byte arrays to the public key information.
byte[] pk = certificado.GetPublicKey();

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.PersistKeyInCsp = false;
//Get an instance of RSAParameters from ExportParameters function.
RSAParameters RSAKeyInfo = rsa.ExportParameters(false);

//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = pk;
//Import key parameters into RSA.
rsa.ImportParameters(RSAKeyInfo);

byte[] cadena_byte = System.Text.Encoding.UTF8.GetBytes(cadena);

System.Security.Cryptography.SHA1CryptoServiceProvider x =
new System.Security.Cryptography.SHA1CryptoServiceProvider();
byte[] data = x.ComputeHash(cadena_byte);

System.Security.Cryptography.MD5CryptoServiceProvider x2 =
new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] data2 = x2.ComputeHash(cadena_byte);

bool result = rsa.VerifyHash(data2, CryptoConfig.MapNameToOID("MD5"), sello_byte);
bool result2 = rsa.VerifyHash(data, CryptoConfig.MapNameToOID("SHA1"), sello_byte);
string smd5 = byte_to_string(data2);
string ssha1 = byte_to_string(data);

//MessageBox.Show("md5=" + smd5+ "\nsha1=" + ssha1+ "\nSello Digital="+ selloDigital);

string ret = "Sello inválido.";

if (result)
{
ret = "Sello válido con digestion MD5 " + hash_md5(cadena);
}
else
{
if (result2)
{
ret = "Sello válido con digestion SHA1 " + hash_sha1(cadena);
}
}
return ret;
}
catch (Exception ex)
{
return "Error al desencriptar el sello digital " + ex.ToString();
}
}

danfred
Mensajes: 4
Registrado: Vie Feb 25, 2011 12:03 pm

Re: Como validar "a mano" un sello digital

Mensajepor danfred » Lun Feb 28, 2011 11:03 am

Listo, validacion del sello digital en c#, aqui el codigo funcional, ya no ocupa openssl todo en punto NET, este codigo ya esta probado, se aceptan comentarios:

public string ValidaSelloDigital(string selloDigital, string cert, string cadena)
{
try
{
byte[] sello_byte = Convert.FromBase64String( selloDigital);
byte[] cert_byte = Convert.FromBase64String( cert);
X509Certificate2 certificado = new X509Certificate2( cert_byte);
string spk = certificado.PublicKey.Key.ToXmlString(false);
AsymmetricAlgorithm pk = AsymmetricAlgorithm.Create();
pk.FromXmlString(spk);
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) pk;
rsa.PersistKeyInCsp = false;
byte[] cadena_byte = System.Text.Encoding.UTF8.GetBytes(cadena);
System.Security.Cryptography.SHA1CryptoServiceProvider x =
new System.Security.Cryptography.SHA1CryptoServiceProvider();
byte[] data = x.ComputeHash(cadena_byte);
System.Security.Cryptography.MD5CryptoServiceProvider x2 =
new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] data2 = x2.ComputeHash(cadena_byte);
bool result = rsa.VerifyHash(data2, CryptoConfig.MapNameToOID("MD5"), sello_byte);
bool result2 = rsa.VerifyHash(data, CryptoConfig.MapNameToOID("SHA1"), sello_byte);
string ret = "Sello inválido.";
if (result)
{
ret = "Sello válido con digestion MD5 " + hash_md5(cadena);
}
else
{
if (result2)
{
ret = "Sello válido con digestion SHA1 " + hash_sha1(cadena);
}
}
return ret;
}
catch (Exception ex)
{
return "Error al desencriptar el sello digital " + ex.ToString();
}
}

roda1984
Mensajes: 2
Registrado: Lun Mar 14, 2011 7:19 pm

Re: Como validar "a mano" un sello digital

Mensajepor roda1984 » Lun Mar 14, 2011 7:23 pm

Hola danfred!

Estoy desarrollando la nueva versión 2011 de la factura electrónica, con el PAC timbrefiscal, al enviar el archivo XML timbrado, el servidor me "responde sello no valido", por lo que quiero validar mi sello antes de enviarlo para ver si corresponde a mi cadena original, con tu codigo que posteaste se puede hacer esto cierto?

Solo tengo dudas, cuales son las entradas a la función:
string selloDigital, string cert, string cadena

Gracias por la ayuda y gran codigo! :)

elliot
Mensajes: 6
Registrado: Lun Abr 04, 2011 10:09 pm

Re: Como validar "a mano" un sello digital

Mensajepor elliot » Lun Abr 04, 2011 10:13 pm

Como genero el archivo xxxx.P12?, para que funcione el codigo de sellado

Saludos

Avatar de Usuario
Dado
Mensajes: 15824
Registrado: Mar Jul 06, 2010 8:56 pm

Re: Como validar "a mano" un sello digital

Mensajepor Dado » Mar Abr 05, 2011 10:56 am

elliot escribió:Como genero el archivo xxxx.P12?, para que funcione el codigo de sellado

Saludos


P12 es lo mismo que pkcs12 y es lo mismo que pfx, busca pfx en el foro hay algunos mensajes al respecto.

Que codigo de sellado estas usando ya que aqui en este foro casi siempre usamos el PEM
ADDENDAS? VALIDACION? CODIGO PARA PROGRAMAR TU PROPIA SOLUCION? TODO LO TENEMOS EN WWW.VALIDACFD.COM VISITANOS !!

elliot
Mensajes: 6
Registrado: Lun Abr 04, 2011 10:09 pm

Re: Como validar "a mano" un sello digital

Mensajepor elliot » Mar Abr 05, 2011 8:13 pm

Estoy usando el archivo de SAT en PKCS8, tendre que cambiarlo a pem y de ahi a pkcs12?

Saludos

elliot
Mensajes: 6
Registrado: Lun Abr 04, 2011 10:09 pm

Re: Como validar "a mano" un sello digital

Mensajepor elliot » Mar Abr 05, 2011 8:42 pm

Hice la conversion y todo funciono muy bien, gracias.

jgraterol
Mensajes: 4
Registrado: Mar May 17, 2011 8:54 pm

Re: Como validar "a mano" un sello digital

Mensajepor jgraterol » Mar May 17, 2011 9:13 pm

Hola!

Retomando este tema, estoy intentando aplicarlo con sha1.

El problema que tengo es con la digestión de la cadena original. Por alguna razón que no entiendo el resultado de hacerlo con

Código: Seleccionar todo

openssl dgst -sha1 "cadoriginal.txt" > sha1dgst.txt
es diferente a lo que reporta el SAT en su validador (https://www.consulta.sat.gob.mx/SICOFI_WEB/ModuloECFD_Plus/ValidadorComprobantes/Validador.asp). La (inmediata) conclusión de que estoy construyendo mal la cadena original creo que no aplica, porque de hecho copio la cadena del resultado mismo de la página y lo pego en el archivo cadoriginal.txt, asegurándome de salvarlo como utf8 y sin caracteres extra. Anexo los archivos necesarios (MHI070814TL6F335.xml, cadoriginal.txt y sha1dgst.txt) a ver si puedes darme una mano con esto.

De antemano muchísimas gracias!
Adjuntos
MHI070814TL6F335.xml
(2.93 KiB) Descargado 556 veces
cadoriginal.txt
(425 Bytes) Descargado 594 veces
sha1dgst.txt
(68 Bytes) Descargado 573 veces

Avatar de Usuario
Dado
Mensajes: 15824
Registrado: Mar Jul 06, 2010 8:56 pm

Re: Como validar "a mano" un sello digital

Mensajepor Dado » Mar May 17, 2011 9:24 pm

jgraterol escribió:Hola!

Retomando este tema, estoy intentando aplicarlo con sha1.

El problema que tengo es con la digestión de la cadena original. Por alguna razón que no entiendo el resultado de hacerlo con

Código: Seleccionar todo

openssl dgst -sha1 "cadoriginal.txt" > sha1dgst.txt
es diferente a lo que reporta el SAT en su validador (https://www.consulta.sat.gob.mx/SICOFI_WEB/ModuloECFD_Plus/ValidadorComprobantes/Validador.asp). La (inmediata) conclusión de que estoy construyendo mal la cadena original creo que no aplica, porque de hecho copio la cadena del resultado mismo de la página y lo pego en el archivo cadoriginal.txt, asegurándome de salvarlo como utf8 y sin caracteres extra. Anexo los archivos necesarios (MHI070814TL6F335.xml, cadoriginal.txt y sha1dgst.txt) a ver si puedes darme una mano con esto.

De antemano muchísimas gracias!


Haz oido del "BOM" (byte order mark)....son 3 bytes que se le estan pegando a tu archivo, al inicio, la unica forma de verlos es con un editor hexadecimal

Busca BOM aqui en el foro, tambien busca un editor hexadecimal pa' quitarle esa mugre

Te anexo el archivo YA SIN EL MOLESTO BOM, haz tus pruebas, checa como el archivo que anexo es 3 BYTES MAS CHICO que el que subiste tu.
Adjuntos
cadoriginal.txt
(422 Bytes) Descargado 642 veces
ADDENDAS? VALIDACION? CODIGO PARA PROGRAMAR TU PROPIA SOLUCION? TODO LO TENEMOS EN WWW.VALIDACFD.COM VISITANOS !!


Volver a “OpenSSL en general (cualquier lenguaje)”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado