Firma electrónica de la factura electrónica ecuatoriana

En el Ecuador el uso de facturas electrónicas (y en general de comprobantes electrónicos) es obligatorio a cada vez más tipos de empresas. Su implementación requiere que tengan firma electrónica ecuatoriana en estándar XAdES-BES (acrónimo de XML Advanced Electronic Signatures – Basic Electronic Signature), sin embargo no especifican con suficiente detalle la forma de implementar tal formato de firma, viéndose las empresas obligadas a utilizar un applet de Java que realice la acción como caja negra. A nivel técnico, esto quería decir que, no importa el lenguaje de programación utilizado, sea Python, .Net, PHP, u otro, era necesario salir de ese entorno para llamar a la funcionalidad en Java, con las molestias y bajas de rendimiento del caso.

A continuación se explicará la implementación de la firma electrónica XAdES BES que acepta el Servicio de Rentas Internas del Ecuador -SRI-. Como prerrequisito se necesita el certificado digital .P12 que lo vende el Banco Central del Ecuador. También es útil la herramienta gratuita del SRI para la facturación electrónica, con la cual se pueden comparar los resultados del firmado.

También te puede interesar la parte dos del artículo donde se implementa la firma digital en JavaScript y se explica el proceso de ingeniería inversa con el cual se obtuvo estos resultados. Adicional, en la parte tres del artículo se listan algunos problemas comunes que surgen en las implementaciones de este algoritmo, se detallan sus causas y se presentan posibles soluciones.

Estructura de la firma electrónica XAdES BES

La estructura de una factura electrónica con firma electrónica en formato XAdES BES  válida es la siguiente:

Estructura de la factura electrónica con firma electrónica
Estructura de la factura electrónica con su firma electrónica

El nodo ds:Signature contiene toda la firma generada y tiene dos namespaces:

  1. xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
  2. xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#"

A continuación se detallan las cuatro partes de la firma electrónica XAdES.

ds:SignedInfo

Guarda el método de canonicalización (c14n), el algoritmo de firmado (SHA1) y tres hash que referencian a los siguientes nodos:

  1. SignedProperties dentro del nodo ds:Object (detallado más abajo en este artículo), que tiene los datos adicionales para implementar el formato XAdES BES.
  2. ds:KeyInfo, con la información del certificado firmante.
  3. comprobante, con la información de la factura electrónica.

Para obtener estos hash es necesario aplicar tanto el método de canonicalización como el algoritmo de firmado previamente mencionados. En la práctica, la canonicalización consiste solamente en agregar los dos namespaces antes indicados al nodo que se va a firmar, respetando todos los saltos de línea, espacios y caracteres especiales . Por ejemplo:

Original:

<ds:KeyInfo Id="Certificate976903">
    ...
</ds:KeyInfo>

Para obtener el hash:

<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#" Id="Certificate976903">
    ...
</ds:KeyInfo>

La excepción sería el hash del nodo comprobante, el cual no se canonicaliza previamente.

Como se mencionó, el algoritmo utilizado para el hash es SHA1, el cual por cierto está siendo reemplazado a nivel mundial por SHA256 debido a las vulnerabilidades descubiertas en su algoritmo. Esperemos que el SRI mejore la seguridad en este sentido.

Para su inclusión en el archivo XML de la factura electrónica firmada, el hash debe ser codificado en base64.

ds:SignatureValue

Es la firma digital codificada en base64 del nodo ds:SignedInfo, previamente canonicalizado.

Actualización al 3 de enero del 2018: Esta parte de la firma, aunque parece relativamente simple (solo se obtendría la firma digital del nodo indicado, no es así?), puede llegar a ser un poco problemática, tal y como se lo detalla en la parte tres del artículo.

ds:KeyInfo

Guarda la información del certificado digital con el que se realiza la firma electrónica.

Tiene dos nodos: ds:X509Datads:KeyValue.

  • El nodo ds:X509Data tiene un solo nodo hijo, ds:X509Certificate, el cual guarda el certificado en formato PEM (acrónimo de Privacy Enhanced Mail, que es la versión codificada en base64 del certificado digital y que originalmente se creó para enviar los certificados binarios vía correo electrónico, de ahí su nombre), sin las cabeceras de inicio y final, y en renglones de 76 caracteres.
  • El nodo ds:KeyValue tiene un nodo hijo, ds:RSAKeyValue, y dos nodos nietos, ds:Modulusds:Exponent. El primero guarda el módulo en base64, y el segundo guarda el exponente, el cual es 65537 codificado en base64, que resulta AQAB. Por cierto, el número 65537 es un número primo de Fermat, exactamente el F4, que es usado ampliamente en algoritmos de encriptación por su bajo peso de Hamming, lo cual es eficiente en cálculos realizados por máquinas binarias.

ds:Object

Almacena información adicional para implementar el estándar XAdES BES. Sin esta sección no serían firmas XAdES sino firmas electrónicas XML clásicas.

Este nodo tiene un solo nodo hijo, etsi:QualifyingProperties, y un solo nodo nieto, etsi:SignedProperties. Este último tiene dos nodos hijos, etsi:SignedSignaturePropertiesetsi:SignedDataObjectProperties.

  • El nodo etsi:SignedSignatureProperties tiene dos nodos hijos, etsi:SigningTimeetsi:SigningCertificate. El primero guarda fecha y hora  de generación en formato ISO 8601 en hora local (YYYY-MM-DDThh:mm:ssTZD, donde TZD es la zona horaria en formato «-hh:mm»), y el segundo tiene la siguiente estructura:
    • etsi:Cert
      • etsi:CertDigest
        • ds:DigestMethod: El mismo algoritmo SHA1 usado anteriormente.
        • ds:DigestValue: el hash del certificado en formato DER (Distinguished Encoding Rules), codificado en base64.
      • etsi:IssuerSerial
        • ds:X509IssuerName: guarda el valor constante (por ahora) de "CN=AC BANCO CENTRAL DEL ECUADOR,L=QUITO,OU=ENTIDAD DE CERTIFICACION DE INFORMACION-ECIBCE,O=BANCO CENTRAL DEL ECUADOR,C=EC". Sería recomendable sacar este valor del mismo certificado digital, para mantener compatibilidad futura.
        • ds:X509SerialNumber: el número serial del certificado digital, en formato decimal, no hexadecimal.
  • El nodo etsi:SignedDataObjectProperties tiene la siguiente estructura:
    • etsi:DataObjectFormat
      • etsi:Description: guarda el valor constante de "contenido comprobante".
      • etsi:MimeType: guarda el valor constante de "text/xml".

Números aleatorios en la estructura de la firma electrónica

Existen ocho números aleatorios enteros entre 1 y 100 mil, que se colocan a lo largo de la estructura de la firma electrónica:

  1. Certificate_number
  2. Signature_number
  3. SignedProperties_number
  4. SignedInfo_number
  5. SignedPropertiesID_number
  6. Reference_ID_number
  7. SignatureValue_number
  8. Object_number

Estos números aleatorios se colocan en atributos de varios nodos, de la siguiente forma:

  1. En ds:KeyInfo, su atributo Id se compone de la siguiente manera: "Certificate" & Certificate_number.
  2. En el segundo nodo hijo ds:Reference del nodo ds:SignedInfo, el atributo URI se compone de la siguiente manera: "#Certificate" & Certificate_number.
  3. En etsi:SignedProperties, su atributo Id se compone de la siguiente manera: "Signature" & Signature_number & "-SignedProperties" & SignedProperties_number.
  4. En el primer nodo hijo ds:Reference del nodo ds:SignedInfo, el atributo URI se compone de la siguiente manera: "#Signature" & Signature_number & "-SignedProperties" & SignedProperties_number.
  5. En ds:Signature, su atributo Id se compone de la siguiente manera: "Signature" & Signature_number.
  6. En ds:Object, su atributo Id se compone de la siguiente manera: "Signature" & Signature_number & "-Object" & Object_number.
  7. En etsi:QualifyingProperties, su atributo Target se compone de la siguiente manera: "#Signature" & Signature_number.
  8. En ds:SignedInfo, su atributo Id se compone de la siguiente manera: "Signature-SignedInfo" & SignedInfo_number.
  9. En el primer nodo hijo ds:Reference del nodo ds:SignedInfo, el atributo Id se compone de la siguiente manera: "SignedPropertiesID" & SignedPropertiesID_number.
  10. En etsi:DataObjectFormat, su atributo ObjectReference se compone de la siguiente manera: "#Reference-ID-" & Reference_ID_number.
  11. En el tercer nodo hijo ds:Reference del nodo ds:SignedInfo, el atributo Id se compone de la siguiente manera: "Reference-ID-" & Reference_ID_number.
  12. En ds:SignatureValue, su atributo Id se compone de la siguiente manera: "SignatureValue" & SignatureValue_number.

Implementación en JavaScript

Para la implementación de la firma electrónica en JavaScript se utilizó la librería Forge tanto para la obtención de los hash SHA1 así como para la extracción de datos del certificado digital, y el firmado en sí. También se utilizó la librería moment.js para la obtención de la fecha y hora de generación.

Para probar la firma electrónica se tiene dos opciones:

  1. Firmar primero con el facturador electrónico gratuito del SRI, luego colocar los ocho números aleatorios presentes en la firma electrónica generada, y con esos números ejecutar la versión JavaScript del generador de firmas. Deben resultar en los mismos valores.
  2. Generar la firma electrónica con la versión JavaScript, codificar todo el contenido del XML resultante en base64, y enviar el texto vía SOAP a los Servicios Web del SRI.

El código fuente se lo puede acceder en GitHub.

Actualización al 25 de octubre de 2016:

Se creó una prueba de concepto donde la firma electrónica se genera 100% local en el navegador, sin recursos de servidor ni enviando información a ninguna parte. Se la puede acceder en https://jsfiddle.net/jybaro/xmvov1c3/

Esta versión, a más de utilizar las librerías Forge y Moment mencionadas antes, también llama a la librería buffer, la cual permite manipular información binaria en el navegador.

Actualización al 28 de diciembre de 2016:

Se ha elaborado un artículo complementario donde se explican detalles sobre la implementación en JavaScript:

Actualizado al 3 de enero de 2018:

Se ha elaborado una tercera parte del artículo con un listado de soluciones a problemas comunes en la implementación de la firma electrónica:

También te puede interesar...

55 comments

  1. Jefferson PIno says:

    Muchas gracias estimado Edgar Valarezo, por el excelente aporte, con la explicacion suya pude implementar la firma electronica, en GeneXus de forma nativa, sin dll o jar.
    Sus publicaciones han sido de mucha ayuda, muchas gracias, es hasta ahora el unico que ha explicado cada uno de los calculos que se realizan para firmar electronicamente.

  2. Carlos says:

    Hola, con el reciente cambio del SRI, tienen idea de lo que hay que cambiar en el proceso de firma???

    El certificado utilizado, no es del tipo firma digital

    1. Edgar Valarezo ( User Karma: 0 ) says:

      A finales del 2019, el SRI realizó cambios en su definición de la factura electrónica. Se está desarrollando una cuarta parte de esta serie de artículos para finales del 2020, donde se recogerán estos cambios.

  3. Francisco says:

    Excelente ayuda amigo… gracias…

    pero te comento que desde hace un tiempo el algoritmo dejo de funcionar ya que aparece que la firma es invalida aun cuando ya estaba probada y funcionando por un buen tiempo atrás, me gustaría saber si sabes el porque y como lo puedo solucionar ya que fuera de gran ayuda

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Como mencionas, el SRI a finales del 2019 realizó cambios en sus definiciones que quebraron las implementaciones de la factura electrónica que no reaccionaron a tiempo. Se está desarrollando para finales del 2020 un cuarto artículo en este blog que recoja los cambios del SRI hasta la fecha.

  4. Jairo says:

    Hola, gran explicación, gracias!
    He logrado implementarlo en PHP, pero aún tengo una duda, ojalá puedas ayudarme a despejarla. Mencionas en el artículo que los números aleatorios van de 1 a 100 mil. Sin embargo en las pruebas que he estado realizando con el facturador del SRI he obtenido números más grandes que eso, por ejemplo 1023814. Así que mi duda es, ¿cuál es el rango apropiado para los números aleatorios?

    Saludos

    1. Edgar Valarezo ( User Karma: 0 ) says:

      En el momento que se estaba realizando la investigación del facturador del SRI no se llegó a detectar un número aleatorio con más de cinco dígitos, de ahí el tope de 100 mil, sin embargo el SRI acostumbra a hacer cambios en su software y en sus definiciones de forma silenciosa y desordenada, por lo que quizás ahora se haya cambiado el umbral máximo de esos números. De ser el caso, recomendaría en lo posible mantener el tope de 100 mil, para permitir la retro compatibilidad con sistemas ya existentes.

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Se lo manda vía SOAP:

      $servicio=»https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl»;
      $client = new SoapClient($servicio, array(‘trace’ => TRUE));
      $result = $client->validarComprobante(array(«xml» => ($facturafirmada)));

      $servicio=»https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl»; //url del servicio
      $client = new SoapClient($servicio, array(‘trace’ => TRUE));
      $result = $client->autorizacionComprobante(array(«claveAccesoComprobante» => $claveacceso));

    1. Hugo Granda says:

      Buenos días, también estoy intentando con php pero tengo algunos inconvenientes podrías ayudarme con el tema, y en el javascript da un error en el saveFile_noui.
      Muchas Gracias.

  5. Christian says:

    Me parece un excelente artículo, el único que explica realmente el detalle de la firma, como lo debería de exponer el SRi en su manual. Yo solía tener el problema de la firma invalida cuando el xml tenía un carácter especial, es decir al momento de leer xml este tenia errores, un( &) por por ejemplo o otro caracter ~ que hacia aparecer el error, en mi caso el problema era porque al guardar el fichero en el sistema no se tomaban encuenta las respectivas validaciones y codificaciones del mismo y al leerlo ya esté venía mal.

  6. Freddy Salinas says:

    Hola, estoy intentando hacer el firmado en php, me funciona con unos certificados y con otros no, salida que la firma estaba caducada, me doy cuenta que viene un array con extracerts, imagino q son necesarios para el firmado pero la funcion sign de open ssl no recibe ningun argumento para extracers, me gustaria tener su asesoria

  7. Santiago Monge says:

    Tengo una consulta, quisiera saber como puedo firmar un documento pero con el dispositivo token, ya que no dispongo del archivo. Hay algún metodo que se pueda usar, sin importar el lenguaje.

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Se puede utilizar un applet de Java para acceder al dispositivo físico y así realizar la firma. El problema del token es que se requiere de drivers para poder acceder a ese hardware especial, por lo que cada lenguaje debe manejar a su manera ese acceso físico. Está en desarrollo Web Crypto API, para manejar este acceso desde el navegador con JavaScript, pero aún es muy experimental.

  8. Vinicio Gomez says:

    Hola buenos días, Edgar Valarezo:

    Felicidades, excelente blog acerca de la firma electrónica, explicado y detallado, ahora bien tengo tres preguntas:
    – Se puede firmar por nodo (XML) en un sólo XML, es decir varias firmas diferentes en un XML?
    -Se podría realizar este firmado en la base de datos (Porque el postgresql puedo generar el XML como campo). Que recomendaría?
    a) Guardar el archivo .p12 en el servidor como archivo.
    b) Extraer la información de la firma y guardar en la base de datos (encriptada) y generar el xml firmado en la BD.
    -Tiene conocimiento de la librería FPDF para firmar PDF, que sale error de firma con el archivo .p12?

    1. Edgar Valarezo ( User Karma: 0 ) says:

      No se puede tener varias firmas en un mismo XML, solo una. Para el servidor recomendaría implementar un servidor PKI donde se pueda almacenar las claves privadas de manera segura. Sobre la librería FPDF, un poco la he usado pero no con la firma.

  9. Richi BPinargote says:

    Hola estoy muy agrdecido, creo que eres la unica persona que explica en detalle como funciona este proceso. ya que es un tema muy monopolizado en el pais por parte de los desarrolladores.
    desearia que me ayuden solventando una duda.. es necesario quitarle el nodo a la factura antes de cifrarla con sh1… estoy haciendo la libreria en php, los resultados son equivalentes, pero el SRI me manda 2 errores…
    1.La firma es invalida [Firma inválida (firma y/o certificados alterados)]
    2.No tiene Cadena de Confianza Valida.

    me preocupa el primer error, creo que no se esta firmando bien el documento,
    crees que por no ser un certificado genuino, me sale el error de la firma alterada o es por que lo estoy firmando mal?

    1. Edgar Valarezo ( User Karma: 0 ) says:

      El primer error puede ser por algún fallo escondido en la generación de la firma, te recomiendo revisar los artículos 2 y 3 en este sitio web sobre el tema. El segundo error es por falla del certificado en sí, ya sea porque es un certificado no oficial o porque está caducado.

  10. Bernardo Leon says:

    Hola, muchas gracias por la explicación, parece ser que es la única que detalla como funciona la firma electrónica. Tengo unas preguntas espero que me puedas ayudar.
    1) Trato de ejecutar el webservice de pruebas de autorización con el xml firmado por el jsfiddle pero me dice que la firma es invalida.
    2) En donde puedo encontrar mas informacion? De donde sacaste la informacion que expones aqui? El supuesto manual del sri no indica como implementar XAdES_bes.
    3) Si trato de autorizar un comprobante previamente no autorizado ese comprobante ya queda registrado para ellos como no autorizado o si puedo probar varias veces con el mismo comprobante? Gracias!

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, qué bueno que en algo ayuda el artículo. Sobre tus consultas:
      1) Mira la parte final de la continuación del artículo, donde se listan algunos errores comunes. Recuerda que un espacio de más, un enter o una minúscula que era mayúscula hará que toda la firma sea distinta. También ten en cuenta que el archivo .p12 puede tener más de una firma privada, y puede que se esté firmando con la firma equivocada.
      2) Como tu lo dices, no hay documentación sobre el tema. Lo que yo hice fue ingeniería inversa del facturador del SRI, mira en el segundo artículo más detalles sobre esto.
      3) En pruebas sí se podía mandar el mismo código varias veces.

  11. Washington Reyes says:

    Hola, tengo implementada la factura electronica en PHP y usando el SOAP nativo de PHP le envio el XML generado al Web Service del SRI de recepcion y me sale RECIBIDA pero me indica error en la estructura del XML, corro el XML en el programa SOAPUI y me lo recibe perfectamente, al ejecutar el WS de autorizacion me dice error en la firma. Necesito el soporte tecnico que me puedas brindar para solucionar mi problema, me puedes contactar al siguiente numero 098???2600 o al 098???6578 para convenir el precio, lo necesito urgente.

  12. Rubén says:

    Estoy probando este código y me parece un muy buen artículo, pero estoy teniendo problemas para validar la firma con los WS del SRI, creo que el mi error esta en la forma en que leo el XML de la factura, debido a que al comparar con otro firmador (colocando las mismas constantes) el valor del SHA1 de la factura que va en SignedInfo varía, he probado borrand espacios entre tags, quitanto saltos de líneas, etc y sigo obteniendo valores diferentes para el SHA1 de la factura? muchas gracias, espero me puedas ayudar con esto

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, verifícale la forma canónica del XML de la factura antes de firmarle, y también ten cuidado con la codificación de caracteres, tal vez alguna tilde o eñe te esté dando problemas. Te puede ayudar la segunda parte del artículo, donde extiendo la manera de probar el algoritmo. Saludos.

  13. Mario says:

    O conoces una manera de pasarle los archivos que no sea a través de un input en html? osea que yo tenga fijo la ruta del P12 y la factura XML (la cual genero en el sistema) se las pase ambas y así se genere el archivo firmado, tendrás algo en mente? saludos.. PD. Soy el del comentario anterior.

    1. Edgar Valarezo ( User Karma: 0 ) says:

      La única manera de pasarle los archivos sin el input HTML y que lea directamente del disco es cargando los archivos en el servidor.

  14. Mario says:

    Hay alguna manera de hacer que esos archivos los cargue automaticamente (sin necesidad del formulario) estoy tratando de adaptarlo a una implementación que tengo (lo unico que me falta es firmar el documento) pero me está costando hacerlo en PHP.

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, sí es posible hacerlo en PHP de manera automática con este algoritmo, tenemos experiencia en lograrlo con PHP, si gustas te podemos mandar una cotización de nuestros servicios. Saludos.

  15. LUIS MORALES says:

    Hola SR. Edgar Valarezo puede escribirme a mi correo nu????em@hotmail.com o agregarme a facebook masterzor LEMR quiero hacerle unas preguntas o Whatsapp +593098???0379 por favor

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Estimado mil disculpas, nuestro tiempo es muy escaso y solo respondemos llamadas y whatsapp bajo contrato de soporte. Si gustas puedes dejar tus dudas en este espacio de comentarios para que las respuestas sirvan al resto, o también puedes contratar nuestros servicios de soporte. Saludos.

  16. Alfonfin says:

    Hola, escribo estas líneas para felicitarte por el artículo y contarte que lo acabo de implentar la firma en visual .net todo nativo, me ha tomado como dos semanas pero sin ésta ayuda créeme que hasta ahora no vería la luz.
    Solo ésta acotación::
    Donde pones: ds:X509SerialNumber: el número serial del certificado digital, podrías aclarar que hay que ponerlo como decimal y no hexadecimal (eso me di cuenta viendo el código).

    Gracias

    1. Roberto Garrido says:

      No existirá manera en que puedas compartirmelo? Quisiera poder implementarlo en PHP y no se por donde arrancar, seria de gran ayuda verlo desarrollado en .net. Gracias!

    2. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, gracias por comentar, te respondí por interno. Está compartida la implementación en JavaScript a fin de ser una prueba de concepto del algoritmo, y que sirva de referencia para ser desarrollado en otros lenguajes. En PHP de pronto te recomendaría revisar una librería que implemente XML digital signature, una búsqueda rápida en Google te puede dar algunos ejemplos.

  17. Alberto says:

    Muy buenas, primero que todo excelente aporte, he estado probando el javascript y me sale sigue saliendo el error de Firma Invalida, ya he probado en todos los enlaces, agradeceria mucho la ayuda.

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, por favor revisa la actualización del artículo sobre XaDES-BES, al final, donde se listan algunos errores comunes en la implementación, saludos.

  18. Santiago Sanchez says:

    Estimado en la libreria xades-bes-sri me sale 2 errores puntuales que por favor me podrian guiar.

    1.- saveFile_noui esta funcion no se encuentra
    2.- TypeError: Argument 1 of File.constructor can’t be converted to a sequence.

    Por favor su ayuda

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Revísale por favor el código que está publicado en la continuación del artículo.

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, favor visita el artículo sobre XaDES-BES, en la parte final hay una actualización de errores comunes en la implementación, espero te pueda servir. Saludos.

  19. William Banchon Vargas says:

    Estimado Mike o Edgar Valarezo,

    Estuve probando el script y me sale el mismo error que publico mike sobre la firma invalida. Alguno de ustedes pudo dar con el error ?

    Gracias

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola, lo he probado nuevamente con el webservice del SRI y no me da el error de firma inválida que mencionas, que debo confesar antes sí daba y que con los ajustes del caso ya fue superado hace unos meses. El error que ahora me da es » ERROR EN DIFERENCIAS«, lo cual quiere decir que se logró verificar la firma del comprobante electrónico y que ahora manda errores ya del contenido de la factura. Con todo intentaré conseguir una segunda firma electrónica para realizar más pruebas, las colaboraciones son bienvenidas.

      Sugiero que te revises la segunda parte del artículo cuyo enlace se lo puede encontrar al final. También aconsejaría tener cuidado con la codificación de caracteres.

  20. Mike says:

    Estimado he probado el código en jsfiddle y me sigue apareciendo error en firma, realizando la depuración observo que el bloque SignatureValue y DigestValue del comprobante, no coinciden.
    Saludos,

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Los nodos SignatureValue y DigestValue no tienen que ver puesto que, como se detalla en el artículo, el primero es la firma del nodo SignedInfo, mientras que el segundo es el hash del certificado.

      Para realizar la depuración sugiero revisar la segunda parte del artículo, cuyo enlace consta al final.

  21. Anónimo says:

    https://jsfiddle.net/jybaro/xmvov1c3/
    Lo he probado con algunas certificados pero no funciona simpre me devuelve
    mensaje = «FIRMA INVALIDA»
    informacionAdicional = «La firma es invalida [Firma inválida (firma y/o certificados alterados)]»
    Quisiera saber si en el nodo ds:SignatureValue, es solamente la firma digital codificada en base64 del nodo ds:SignedInfo, o tiene que ir algun otro valor

    1. Edgar Valarezo ( User Karma: 0 ) says:

      Hola,
      Corregido. Había un error en JSFiddle al obtener la firma digital del nodo SignedInfo, donde se estaba reutilizando una variable que ya estaba instanciada antes. Está probado en el servicio Web del SRI y ya no sale el error de «firma inválida». La corrección está subida al mismo JSFiddle.
      Tal y como se detalla en el artículo, la firma es solo de ese nodo, previa canonicalización.
      Gracias por el aviso!

    1. Edgar Valarezo ( User Karma: 0 ) says:

      No la verdad ya que el objetivo no era implementar el algoritmo en cada lenguaje, sino entender cómo va el algoritmo para que se lo pueda implementar sobre cualquier tecnología. Pero como reto y en mi caso para aprender Python de paso, suena interesante mi amigo…

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *