etobella / python-xades

Xades Signature for Python
GNU Lesser General Public License v3.0
31 stars 27 forks source link

Invalid Signature #3

Closed jaullo closed 5 years ago

jaullo commented 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?

devsergioraar commented 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 ``

jaullo commented 5 years ago

@sergioraar Do you have the same problem? Is you signature passing ministerio de hacienda validations?

devsergioraar commented 5 years ago

@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 x.test_sign() 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)

jaullo commented 5 years ago

@sergioraar trabajemoslo en conjunto

devsergioraar commented 5 years ago

@sergioraar trabajemoslo en conjunto

Mae puede funcionar. 8913-3112

devsergioraar commented 5 years ago

https://api.whatsapp.com/send?phone=50689133112&text=BretePython

etobella commented 5 years ago

@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

etobella commented 5 years ago

Además, estas cumpliendo la política de firma? Esta libreria te da una forma sencilla de configurarlo, pero es necesario configurar alguna cosa.

jaullo commented 5 years ago

@etobella en mi caso, yo genero todo el xml y la firma, inclusive colocando la política de firma. Pero me pasan varias cosas:

  1. 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

  2. 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,

etobella commented 5 years ago

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é.

etobella commented 5 years ago

Pasame un ejemplo de como sacas el xml a ver si te puedo dar alguna idea

jaullo commented 5 years ago

@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

etobella commented 5 years ago

Puedes probar con etree.tostring(root, xml_declaration=True, encoding='UTF-8')

etobella commented 5 years ago

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.

jaullo commented 5 years ago

@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

etobella commented 5 years ago

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?

jaullo commented 5 years ago

@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

etobella commented 5 years ago

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?

jaullo commented 5 years ago

@etobella dime tu usuario de gitlab y te doy acceso

etobella commented 5 years ago

etobella también

variux commented 5 years ago

@jaullo logró hacer funcionar la librería con el ministerio de Hacienda?

etobella commented 5 years ago

@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,

etobella commented 5 years ago

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

variux commented 5 years ago

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

etobella commented 5 years ago

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.

etobella commented 5 years ago

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 😄

etobella commented 5 years ago

@jaullo Al final lo resolviste?

etobella commented 5 years ago

@jaullo Any news?

jaullo commented 5 years ago

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

etobella commented 5 years ago

Ok, pues lo cierro pues