Closed jaullo closed 5 years ago
HI, i'm trying to use your code to sign electronic invoices in Costa Rica, your code works but i always get the error "Invalida Signature". If i check the final signature with some tool i get data:data and digest doesn't match. Any idea what i'm doing wrong? ``Exception has occurred: StopIteration exception: no description File "/home/sergio/Escritorio/PROYECTOSMAY2018/haciendaPython/src/lxml/lxml.etree.pyx", line 2821, in lxml.etree._ElementMatchIterator.next (src/lxml/lxml.etree.c:75265) File "/home/sergio/Escritorio/PROYECTOSMAY2018/haciendaPython/haciendaCode/pythoncorella/test/test_xades.py", line 98, in test_create_2 xmlsig.template.add_transform(ref, xmlsig.constants.TransformEnveloped) File "/home/sergio/Escritorio/PROYECTOSMAY2018/haciendaPython/haciendaCode/pythoncorella/test/test_xades.py", line 150, in
x.test_create_2() File "/usr/lib/python3.6/runpy.py", line 85, in _run_code exec(code, run_globals) File "/usr/lib/python3.6/runpy.py", line 96, in _run_module_code mod_name, mod_spec, pkg_name, script_name) File "/usr/lib/python3.6/runpy.py", line 263, in run_path pkg_name=pkg_name, script_name=fname)
PROBLEMS OUTPUT DEBUG CONSOLE TERMINAL
Find ``
@sergioraar Do you have the same problem? Is you signature passing ministerio de hacienda validations?
@sergioraar Do you have the same problem? Is you signature passing ministerio de hacienda validations?
Hello, I have an issue on this. The test_xades.py does not run. I have check the Python files, but I do not understand them. I am considering writing my own lib. This work is almost useless. It needs documentation.
Fails on
sign = root.xpath(
'//ds:Signature', namespaces={'ds': xmlsig.constants.DSigNs}
)[0]
Error Message says:
Exception has occurred: IndexError
list index out of range
File "/home/sergio/Escritorio/PROYECTOSMAY2018/haciendaPython/haciendaCode/pythoncorella/test/test_xades.py", line 29, in test_sign
)[0]
File "/home/sergio/Escritorio/PROYECTOSMAY2018/haciendaPython/haciendaCode/pythoncorella/test/test_xades.py", line 153, in
@sergioraar trabajemoslo en conjunto
@sergioraar trabajemoslo en conjunto
Mae puede funcionar. 8913-3112
@sergioraar Como es el fichero que estas usando? El problema que te da es que no tienes definido el nodo de firma. Para crearlo debe usar algo parecido a esto. https://github.com/etobella/python-xades/blob/master/test/test_xades.py#L41
Además, estas cumpliendo la política de firma? Esta libreria te da una forma sencilla de configurarlo, pero es necesario configurar alguna cosa.
@etobella en mi caso, yo genero todo el xml y la firma, inclusive colocando la política de firma. Pero me pasan varias cosas:
En los valores del certificado me salen /n y /r según reviso estos valores los mete el xmlsig usando los tails y text, como puedo hacer para dejar esa xml de firma limpio de esos valores sin invalidarla
Lo otro es que cuando lo reviso en validadores de firma me da el error del data:data and digest doesn't match
Lo he estado viendo con @sergioraar pero no hemos dado con soluciones. Alguna idea? O inclusive si nos podes dar un soporte lo conversamos Saludos,
no debes quitarlo ni tabuladores ni intros (ni añadirlos) No es obligatorio sacarlo. Por eso te falla el match.
Seguramente puede ser que el problema sea que haces un pretty_print del xml. No lo hagas, sacalo como esté.
Pasame un ejemplo de como sacas el xml a ver si te puedo dar alguna idea
@etobella esta es la forma en la que estoy sacandolo
def test_create_2(cert, password, xml):
xml_decoder = base64decode(xml)
root = signature.base.parse_xml(xml_decoder)
signature2 = xmlsig.template.create(
xmlsig.constants.TransformInclC14N,
xmlsig.constants.TransformRsaSha256,
"Signature-699c7ef9-4df9-4c2e-96a3-18fde3498d3e"
)
ref = xmlsig.template.add_reference(
signature2, xmlsig.constants.TransformSha256, uri="", name="Reference-9765986a-17ac-418f-b1ca-ed2d5e106042"
)
xmlsig.template.add_transform(ref, xmlsig.constants.TransformEnveloped)
xmlsig.template.add_reference(
signature2, xmlsig.constants.TransformSha256, uri="#KeyInfoId-Signature-699c7ef9-4df9-4c2e-96a3-18fde3498d3e",
name="ReferenceKeyInfo"
)
xmlsig.template.add_reference(
signature2, xmlsig.constants.TransformSha256,
uri="#SignedProperties-Signature-699c7ef9-4df9-4c2e-96a3-18fde3498d3e",
uri_type="http://uri.etsi.org/01903#SignedProperties"
)
ki = xmlsig.template.ensure_key_info(signature2, name='KeyInfoId-Signature-699c7ef9-4df9-4c2e-96a3-18fde3498d3e')
data = xmlsig.template.add_x509_data(ki)
xmlsig.template.x509_data_add_certificate(data)
xmlsig.template.add_key_value(ki)
qualifying = signature.template.create_qualifying_properties(signature2,
name="QualifyingProperties-9fa5f605-45b8-44e5-b650-698f16fe3d21")
signature.utils.ensure_id(qualifying)
props = signature.template.create_signed_properties(
qualifying, name="SignedProperties-Signature-699c7ef9-4df9-4c2e-96a3-18fde3498d3e"
)
policy = signature.policy.GenericPolicyId(
'https://tribunet.hacienda.go.cr/docs/esquemas/2016/v4/Resolucion%20Comprobantes%20Electronicos%20%20DGT-R-48-2016.pdf',
u"Politica de Firma Ministerio Hacienda v4.2",
xmlsig.constants.TransformSha1
)
signed_do = signature.template.ensure_signed_data_object_properties(props)
signature.template.add_data_object_format(
signed_do,
"#Reference-9765986a-17ac-418f-b1ca-ed2d5e106042",
description="Desc",
mime_type="application/xml",
encoding='UTF-8'
)
root.append(signature2)
ctx = signature.xades_context.XAdESContext(policy)
certificate = crypto.load_pkcs12(base64.b64decode(cert), password)
ctx.load_pkcs12(certificate)
ctx.sign(signature2)
basexml = etree.tostring(root, encoding = "unicode")
ctx.verify(signature2)
return basexml
Pero siempre que lo envío con mi factura me responde con firma invalida El etree.tostring con el unicode lo pongo para poder quitar el bites que devuelve por defecto para poder enviarlo al servidor de pruebas
Puedes probar con etree.tostring(root, xml_declaration=True, encoding='UTF-8')
Alguna vez, tenia problemas con espacios en blanco entre tags i los eliminaba haciendo tree = etree.fromstring( xml_facturae, etree.XMLParser(remove_blank_text=True)) xml_facturae = etree.tostring(tree, xml_declaration=True, encoding='UTF-8') root = etree.fromstring(xml_facturae) antes de hacer nada. Prueba a ver.
@etobella probé lo pasos indicados pero a la hora de generar el resultado queda así
<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<FacturaElectronica
Y eso me causa un error, yo estoy usando python 3.6 y 3.7
Vale, el problema creo que es a la hora de exportar el string al fichero. Tienes que pensar que una vez firmado el fichero es muy sensible y se tiene que vigiliar de no editar nada. En el código original ponías que encoding = 'unicode', vigila que no al poner UTF-8 no dé alguna diferencia. También podría ser que al guardar el fichero no hubieras visto que falté codificar el resultado en utf-8 o que se debe exportar directamente como bytes. Tienes el código en algun repositorio para ver si te puedo ayudar mejor?
@etobella no tengo un ejemplo como tal a mano porque estoy tratando de integrarlo en odoo y enviando al servidor de pruebas del Ministerio de hacienda de costa rica. Pero, si tuvieses tiempo te puedo abrir una sesión remota a mi equipo de desarrollo para que lo veas
En l10n-spain de la OCA está el módulo español con la firma para el caso español. No utiliza esta librería por que no la tenía aún, pero funciona perfectamente. Talvez te interesa como ejemplo. Y el código en odoo lo tienes disponible?
@etobella dime tu usuario de gitlab y te doy acceso
etobella también
@jaullo logró hacer funcionar la librería con el ministerio de Hacienda?
@jaullo ¿Has conseguido que funcione? No he encontrado la documentación técnica de la política de firma de la factura electrónica costariqueña como para deciros nada más, ni he recibido ninguna notificación del repositorio que comentabas.
Saludos,
Al final he conseguido algo: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=2ahUKEwjlkue4sd_iAhXIyYUKHdmGCPkQFjAAegQIAhAC&url=https%3A%2F%2Ftribunet.hacienda.go.cr%2Fdocs%2Fesquemas%2F2016%2Fv4.2%2FANEXOS%2520Y%2520ESTRUCTURAS_V4.2.pdf&usg=AOvVaw1Rf5QsYH2GQK_uuDL9e-2w En principio no tiene nada extraño y deberia ser sencillo firmar de la misma forma que te estan proponiendo
No hay realmente una buena documentación, esa sería para la versión 4.2, ahora está la versión 4.3, Con un firmador con el que estuve trabajando en node js el Ministerio de Hacienda costarricense parecía estarlo rechazando y era por un tema en específico de ellos (del Ministerio de Hacienda) voy a probar este, sólo esperaba a ver si alguno había logrado hacer que funcione
Pero tienes el técnico para el 4.3? El tema con la firma es conseguir que no haya diferencias entre lo firmado y lo que guardas, ya que por accidente puede dar problemas. En principio está libreria funcionaba con la factura española y si se sigue la misma política de firma (normalmente no se toca) debería funcionar de forma parecida al test https://github.com/etobella/python-xades/blob/master/test/test_xades.py#L88 pero deberia eliminarse las línea 99, 100, 101 y poniendo en la política la URL específica.
Tengo dudas si funcionaria el XPATH de transformación debido a que ellos añaden uno con: not(ancestor-or-self::ds:Signature)
. El problema seria cosa de que lxml no lo tolera y allí no puedo hacer nada 😢. Podria ser necesario añadir algun transform más para dejarlo igual, pero en rango generales seria lo comentado.
Deberia funcionar correctamente, pero no sabria como ponerlo de forma sencilla en un post... Pruebalo y si no lo consigues intento ponerlo en algun fichero, como esquema. No deberia ser problema partiendo de los ejemplos que existen tanto en python-xades como en python-xmlsig.
Si quieres que te lo revise, dejalo en algún repo de github y me haces un ping para verlo y así darte un poco de help 😄
@jaullo Al final lo resolviste?
@jaullo Any news?
Sí, lo logramos, bastante el cambio que se hizo para que funcionara, casi tipo "hack". Lo ideal sería ajustar todo bien, pero no hemos tenido tiempo
Ok, pues lo cierro pues
HI, i'm trying to use your code to sign electronic invoices in Costa Rica, your code works but i always get the error "Invalida Signature". If i check the final signature with some tool i get data:data and digest doesn't match. Any idea what i'm doing wrong?