Imagen

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


.

verificación de una firma electrónica desde un xml

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 ]]
mitto_33
Mensajes: 7
Registrado: Mar Abr 12, 2011 2:39 pm

verificación de una firma electrónica desde un xml

Mensaje por mitto_33 »

Hola a todos, antes que nada agradecer por toda la información que aquí se ha publicado puesto que me ha sido bastante útil.

Actualmente ya cuento con un sitio de facturación electrónica CFDi y estoy programando un modulo en php donde mis proveedores subirán las facturas que me han emitido (archivos xml), lo que tengo que hacer es verificar la integridad de las facturas que allí se suban, eso de integridad me esta dando dolor de cabeza, puesto que aún no sé todo lo que tengo que analizar y validar, mi jefe me pidió que inicialmente verificara que la firma electrónica del xml fuera correcta y que con eso estaríamos seguros que la información contenida en el xml no ha sido alterada, la verdad tengo mis dudas sobre si eso es cierto.

he estado leyendo que con openssl se puede validar si la firma electronica es correcta, pero no sé como hacerlo, por el momento extraigo la cadena original y el certificado que viene dentro del xml, pero no sé como utilizarlos, he leido que puedo utilizar la función openssl_verify(), la he utilizado pero sin éxito.

Les dejo un pequeño código que he utilizado en php. Esta recibe según yo la cadena original ($data) y el certificado (extraído del xml), aún no sé que debe llevar el parametro $signature, pero la función marca esta alerta "Warning: openssl_verify() [function.openssl-verify]: supplied key param cannot be coerced into a public key in"

Espero que alguien me pueda orientar en como hacer para validar la firma electrónica y que otras cosas debería hacer para verificar la integridad de las facturas.

Código: Seleccionar todo

<?php

$dada = cadena original del xml
$signature =  ???
$cert = certificado extraído del xml

$ok = openssl_verify($data, $signature, $cert);
if ($ok == 1) {
    echo "good";
} elseif ($ok == 0) {
    echo "bad";
} else {
    echo "ugly, error checking signature";
}
?>
Gracias
Avatar de Usuario
Dado
Mensajes: 15980
Registrado: Mar Jul 06, 2010 7:56 pm

Re: verificación de una firma electrónica desde un xml

Mensaje por Dado »

Es un poquitin mas complejo que lo que estas haciendo.

Checa este mensaje, es un tutorial de como validar con OpenSSL
ADDENDAS? VALIDACION? CODIGO PARA PROGRAMAR TU PROPIA SOLUCION? TODO LO TENEMOS EN WWW.VALIDACFD.COM VISITANOS !!
mauricio
Mensajes: 372
Registrado: Mié Ago 11, 2010 1:55 am
Ubicación: México, D.F.
Contactar:

Re: verificación de una firma electrónica desde un xml

Mensaje por mauricio »

Aquí también puedes ver como verificar el sello: http://cofradia.org/2010/12/29/how-to-d ... -facturas/

Saludos
Todo lo que no es dado es perdido
mitto_33
Mensajes: 7
Registrado: Mar Abr 12, 2011 2:39 pm

Re: verificación de una firma electrónica desde un xml

Mensaje por mitto_33 »

DADO escribió:Es un poquitin mas complejo que lo que estas haciendo.

Checa este mensaje, es un tutorial de como validar con OpenSSL
mauricio escribió:Aquí también puedes ver como verificar el sello: http://cofradia.org/2010/12/29/how-to-d ... -facturas/

Saludos
Gracias Dado y Mauricio por las guias que me proporcionaron, estuve revisando ambas y veo que los procedimientos son muy similares. En mi caso yo utilizo la libreria Openssl que viene integrada con PHP 5.2.6 para validar el sello, ahi tengo todas las instrucciones que aparecen en sus guias.

Mi codigo siempre me arroja que el sello no es valido y no encuentro el porque, actualmente el programa validaCFD me dice que el sello del xml con el que estoy trabajando es valido, lo que estoy haciendo es tomar la cadena original generada por el programa ValidaCFD (esta cadena es igual a la que arroja mi función), saco la llave publica del certificado original ( archivo Pem) del emisor de la factura y tomo el sello que viene en el xml para despues pasarle estos tres datos como parametros a la funcion openssl_verify(), esta función me arroja false si el sello no es valido o true si es valido.

Les pongo el código que estoy utilizando, ya revise la cadena original y esta bien, como comente anteriormente es la misma que arroja el validaCFd, la llave publica la extraigo del certificado (archivo pem) de mi factura, mi unica duda es con el sello que extraigo en el xml, segun yo el sello viene en formato base 64 y hay que pasarlo a binario, para eso utilizo la funcion base64_decode de php, la cual arroja como resultado un binario segun la documentacion de php, pero no estoy seguro de que eso sea correcto.

Que mas puedo verificar?

Código: Seleccionar todo

 $fp=fopen("libs/cfdiLibs/CUAS.CER.PEM","r");
     $pubkey=fread($fp,8192);
     fclose($fp);
     $pubkey  = openssl_get_publickey($pubkey);
 				
    $CO = "||3.0|2011-12-06T19:56:39|ingreso|Pago en una sola exhibicion|1000|0|1|MXN|1190|UAS651204MZ9|UNIVERSIDAD AUTONOMA DE SINALOA|GRAL ANGEL FLORES PONIENTE SIN NUMERO|SIN NUMERO|CENTRO|CULIACAN DE ROSALES|CULIACAN DE ROSALES|SINALOA|MEXICO|80000|COP920428Q20|COPPEL SA DE CV|REPUBLICA 2855 PTE|2855|RECURSOS HIDRAULICOS|CULIACAN|CULIACAN|SINALOA|MEXICO|80105|1|5002|RENTA DE AULA DE COMPUTO|1000|1190|IVA|16|160|160|1.0|0.00|30|ISH|3|30||";

$sello= "ACum9iy1e2U/zG7H4X25W9wz0Kqm/OX8zVH330fZWctOC/F2dW/kJGI4gNF/JA2Njtx6DgDL8jF0RamSA+tk9RhmSvVrXfEvL3cTPIfATv31GESf71yosxb3YMiKAElduMIH/Zm4gwKIwq/7VjtIEWlwhVMVnf0sjNYIAMr7CpQ=";
     $sello = base64_decode($sello); 							
     $valido = openssl_verify($CO,$sello,$pubkey);
    if ($valido){
          $exito= "Sello del emisor valido.";
     }else{
           $error =  "El sello del emisor no es valido.";
     }
Espero puedan orientarme.
Saludos y gracias de antemano.
Avatar de Usuario
Dado
Mensajes: 15980
Registrado: Mar Jul 06, 2010 7:56 pm

Re: verificación de una firma electrónica desde un xml

Mensaje por Dado »

Talvez te falta especificar que use SHA1

int openssl_verify ( string $data , string $signature , mixed $pub_key_id [, int $signature_alg = OPENSSL_ALGO_SHA1 ] )

mmmh, revisa el TIPO DE DATO que espera la funcion, en especial : string $signature

es posible que en este caso NO SE NECESITE la instruccion $sello = base64_decode($sello);

pub_key_id es tipo mixed???

es lo que ODIO de PHP (loose types) :evil:
ADDENDAS? VALIDACION? CODIGO PARA PROGRAMAR TU PROPIA SOLUCION? TODO LO TENEMOS EN WWW.VALIDACFD.COM VISITANOS !!
mauricio
Mensajes: 372
Registrado: Mié Ago 11, 2010 1:55 am
Ubicación: México, D.F.
Contactar:

Re: verificación de una firma electrónica desde un xml

Mensaje por mauricio »

Hola...

Te adjunto en pequeño ejemplo con todo lo necesario para probar:

una factura XML
un certificado PEM
codigo en PHP para validar

Solo faltaría automatizar la obtención del certificado y su transformación a PEM, pero para empezar este codigo ya valida correctamente.

Saludos
Adjuntos
validacfd_php.zip
(6.58 KiB) Descargado 774 veces
Todo lo que no es dado es perdido
mitto_33
Mensajes: 7
Registrado: Mar Abr 12, 2011 2:39 pm

Re: verificación de una firma electrónica desde un xml

Mensaje por mitto_33 »

mauricio escribió:Hola...

Te adjunto en pequeño ejemplo con todo lo necesario para probar:

una factura XML
un certificado PEM
codigo en PHP para validar

Solo faltaría automatizar la obtención del certificado y su transformación a PEM, pero para empezar este codigo ya valida correctamente.

Saludos
Hola de nuevo,

Gracias por el codigo proporcionado mauricio, te soy sincero, no sabia que se podria obtener la cadena original por medio del xslt, la verdad me hubiera ahorrado toda la programación que ya tengo. Probé el ejemplo que me diste y funcionó a la perfección, veo que el ejemplo es para un cfd v 2.0, estoy probando con un cfdi v 3.0 y supuse que el archivo xslt cambia, he descargado ya varios xslt, incluso uno del sitio del SAT llamado cadenaoriginal_3_0.xslt, pero siempre he tenido errores al leerlo, errores como cuando falta una tag por cerrar o abrir en el xslt.

He leido que las versiones actuales de los xslt para el cfd y cfdi son v2.2 y v3.2 respectivamente, pero no encuentro dichos archivos.

Donde podría descargar los archivos correctos? El que descargo del SAT me marca errores o tal vez no estoy bajando el correcto.
¿Podrias probar el ejemplo con un CFDi v3?

Gracias por tu valiosa ayuda
Saludos
mitto_33
Mensajes: 7
Registrado: Mar Abr 12, 2011 2:39 pm

Re: verificación de una firma electrónica desde un xml

Mensaje por mitto_33 »

descargue otro archivo XSLT y ahora solo tengo estos warnings con errores de compilacion del xslt... parece ser que hay un problema con los archivos dependendientes que estan en el sat, sigo investignado..

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file file:///D:/Inetpub/wwwroot/SubirFac/valida/cadenaoriginal_3_0.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cf ... erias.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cfd/ecc/ecc.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cf ... donat.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cf ... visas.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cfd/ecb/ecb.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cf ... lista.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cf ... local.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: compilation error: file http://www.sat.gob.mx/sitio_internet/cf ... ceros.xslt line 2 element stylesheet in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19

Warning: XSLTProcessor::importStylesheet() [xsltprocessor.importstylesheet]: xsl:version: only 1.0 features are supported in D:\Inetpub\wwwroot\SubirFac\valida\index.php on line 19
sortiz
Mensajes: 7
Registrado: Mié Nov 23, 2011 3:02 pm

Re: verificación de una firma electrónica desde un xml

Mensaje por sortiz »

Como ya se ha mencionado en otras hilos, los archivos XLST que publica el SAT declaran requerir la versión 2.0, pero no utilizan ninguna de las características de esa versión, así que si los editas para que digan version="1.0" todo debería funcionar como se espera.

Saludos.
naringas
Mensajes: 22
Registrado: Mié Ago 10, 2011 9:58 am

Re: verificación de una firma electrónica desde un xml

Mensaje por naringas »

Aquí esta como convertir el certificado como viene en el archivo XML a un formato que entienda openssl en PHP:

Código: Seleccionar todo

// CARGA LOS DATOS
$year            = año del CFD
$certificado     = como está en el XML
$sello           = como está en el XML
$cadena_original = desde el XSLT

// PROCESAMIENTO DEL CERTIFICADO
// se hacen varias cosas:
//   primero decodifican las entidades HTML (por ejemplo: #x0A;)
//   luego elimina todos los espacios en blanco, saltos de línea, tabuladores, etc...
$cert = preg_replace('/\s+/', '', html_entity_decode($certificado, ENT_QUOTES, 'UTF-8'));

// Convertir a PEM para poder leer con openssl_pkey_get_public() - aquí está el "truco"
$pem_cert  = "-----BEGIN CERTIFICATE-----\r\n";
$pem_cert .= wordwrap($cert, 64, "\r\n", true);
$pem_cert .= "\r\n-----END CERTIFICATE-----";

// openssl lo debe cargar sin chistar
$pub_key = openssl_pkey_get_public($pem_cert);

// Verifica con MD5 lo del 2010
if ($year <= 2010)
  $v = openssl_verify($cadena_original, base64_decode($sello), $pub_key, OPENSSL_ALGO_MD5);
else
  $v = openssl_verify($cadena_original, base64_decode($sello), $pub_key, OPENSSL_ALGO_SHA1);
Cerrado