
DESCARGA SOFTWARE PARA FACTURA ELECTRONICA DE AQUI.
Facturacion, Validacion, Addendas, Librerias de programacion, etc.
CARTA PORTE V3.1
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
.
Como validar "a mano" un sello digital
-
- Mensajes: 4
- Registrado: Vie Feb 25, 2011 11:03 am
Re: Como validar "a mano" un sello digital
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.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();
}
}
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.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();
}
}
-
- Mensajes: 4
- Registrado: Vie Feb 25, 2011 11:03 am
Re: Como validar "a mano" un sello digital
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();
}
}
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();
}
}
-
- Mensajes: 4
- Registrado: Vie Feb 25, 2011 11:03 am
Re: Como validar "a mano" un sello digital
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();
}
}
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();
}
}
-
- Mensajes: 2
- Registrado: Lun Mar 14, 2011 6:19 pm
Re: Como validar "a mano" un sello digital
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!
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!

-
- Mensajes: 6
- Registrado: Lun Abr 04, 2011 9:09 pm
Re: Como validar "a mano" un sello digital
Como genero el archivo xxxx.P12?, para que funcione el codigo de sellado
Saludos
Saludos
- Dado
- Mensajes: 15980
- Registrado: Mar Jul 06, 2010 7:56 pm
Re: Como validar "a mano" un sello digital
P12 es lo mismo que pkcs12 y es lo mismo que pfx, busca pfx en el foro hay algunos mensajes al respecto.elliot escribió:Como genero el archivo xxxx.P12?, para que funcione el codigo de sellado
Saludos
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 !!
-
- Mensajes: 6
- Registrado: Lun Abr 04, 2011 9:09 pm
Re: Como validar "a mano" un sello digital
Estoy usando el archivo de SAT en PKCS8, tendre que cambiarlo a pem y de ahi a pkcs12?
Saludos
Saludos
-
- Mensajes: 6
- Registrado: Lun Abr 04, 2011 9:09 pm
Re: Como validar "a mano" un sello digital
Hice la conversion y todo funciono muy bien, gracias.
-
- Mensajes: 4
- Registrado: Mar May 17, 2011 7:54 pm
Re: Como validar "a mano" un sello digital
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 es diferente a lo que reporta el SAT en su validador (https://www.consulta.sat.gob.mx/SICOFI_ ... idador.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!
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
De antemano muchísimas gracias!
- Adjuntos
-
- MHI070814TL6F335.xml
- (2.93 KiB) Descargado 807 veces
-
- cadoriginal.txt
- (425 Bytes) Descargado 879 veces
-
- sha1dgst.txt
- (68 Bytes) Descargado 788 veces
- Dado
- Mensajes: 15980
- Registrado: Mar Jul 06, 2010 7:56 pm
Re: Como validar "a mano" un sello digital
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 hexadecimaljgraterol 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 cones diferente a lo que reporta el SAT en su validador (https://www.consulta.sat.gob.mx/SICOFI_ ... idador.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.Código: Seleccionar todo
openssl dgst -sha1 "cadoriginal.txt" > sha1dgst.txt
De antemano muchísimas gracias!
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 871 veces
ADDENDAS? VALIDACION? CODIGO PARA PROGRAMAR TU PROPIA SOLUCION? TODO LO TENEMOS EN WWW.VALIDACFD.COM VISITANOS !!