Buscar en este blog

Cargando...

viernes, 24 de mayo de 2013

Cómo firmar el DTE

Cómo se firma el DTE


Bueno en este tema existen muchos que pueden dar una opinión acerca de cómo realizar esta tarea, sin embargo la experiencia me ha demostrado que el problema no es firmar el documento sino más bien que es lo que debemos firmar. Muchas personas me dicen que firman sus documentos DTE pero al momento de enviarlos al SII este les regresa que la firma es inválida. Expondré aquí la forma que utilizo personalmente para realizar el proceso, sin perjuicio que existan otros desarrolladores que utilicen una forma mas elegante.

Consideraciones generales

Una de las primeras cosas que realizo al momento de intentar firmar el documento DTE es ordenar la información a firmar. Los desarrolladores con más experiencia en este tema saben que al construir un documento XML este no es necesariamente el mismo cuando uno lo visualiza en otros visualizadores de documentos XML. Bueno regresando a lo nuestro, primero ordenemos el DTE

Identación



Si Ud. Cuenta con un documento DTE con estas características lo primero que debería hacer es quitar la identación del documento. Esto tiene una razón, puesto que el CAF entregado por el SII no trae identación es preferible dejar todo el documento alineado según el CAF. Entonces al momento de calcular la firma sobre el CAF no generará errores de timbre. Esta es mi opinión, no exenta de comentarios y observaciones.



















Deje el documento DTE de esta forma.


















CAF

Una vez ordenado el documento DTE, es necesario agregar el CAF al documento, para esto es necesario tomar el nodo CAF desde el archivo de autorización de folios del SII. Cuando digo tomar, es rescatar el nodo sin realizar ninguna modificación o identación. El nodo CAF debe ser insertado tal cual en el documento DTE. Si se modifica de alguna forma el cálculo del timbre fallará.

Entonces segun esto el DTE debería quedar como sigue:




Posterior a esto se encuentra la generación del timbre del TED, cuya información se encuentra disponible en la sección Ejemplo Timbre Electrónico del DTE . Cuando genere el timbre del TED su DTE debería tener esta forma:















Aplicar Firma al DTE


Bueno ya tiene preparado su DTE para ser firmado. Ahora debemos aplicar la siguiente rutina de firma al DTE expuesto. Antes debo señalar que al momento de abrir el documento XML en .Net utilice la propiedad PreserveWhiteSpace = true del objeto XmlDocument. Esto logra abrir el DTE sin ordenar los nodos o identarlo. Si no lo hace de esta forma el timbre que calculo se invalidará.

Una vez abierto el DTE (xml) puede aplicar esta rutina para su firmado:




#region FIRMA DTE

public static void firmarDocumentoXml(ref XmlDocument xmldocument, X509Certificate2 certificado, string referenciaUri )
{
 ////
 //// Cree el objeto SignedXml donde xmldocument
 //// representa el documento DTE preparado para
 //// ser firmado. Recuerde que debe ser abierto 
 //// con la propiedad PreserveWhiteSpace = true
 SignedXml signedXml = new SignedXml(xmldocument);

 ////
 //// Agregue la clave privada al objeto signedXml
 signedXml.SigningKey = certificado.PrivateKey;

 ////
 //// Recupere el objeto signature desde signedXml
 Signature XMLSignature = signedXml.Signature;

 ////
 //// Cree la refrerencia al documento DTE
 //// recuerde que la referencia tiene el 
 //// formato '#reference'
 //// ejemplo '#DTE001'
 Reference reference = new Reference();
 reference.Uri = referenciaUri;

 ////
 //// Agregue la referencia al objeto signature
 XMLSignature.SignedInfo.AddReference(reference);
 KeyInfo keyInfo = new KeyInfo();
 keyInfo.AddClause(new RSAKeyValue((RSA)certificado.PrivateKey));

 ////
 //// Agregar información del certificado x509
 keyInfo.AddClause(new KeyInfoX509Data(certificado));
 XMLSignature.KeyInfo = keyInfo;

 ////
 //// Calcule la firma y recupere la representacion
 //// de la firma en un objeto xmlElement
 signedXml.ComputeSignature();
 XmlElement xmlDigitalSignature = signedXml.GetXml();

 ////
 //// Inserte la firma en el documento DTE
 xmldocument.DocumentElement.AppendChild(xmldocument.ImportNode(xmlDigitalSignature, true));

}



#endregion

Para ser honesto esta rutina es capaz de firmar el DTE y El SETDTE solo se debe pasar la referencia adecuada para indicar que nodo debe firmar.


Bueno espero que esta breve rutina les permita avanzar en sus proyectos. Como siempre los invito a dejar un comentario acerca de como mejorar estas rutinas.



56 comentarios:

  1. estimado una consulta, existe alguna instruccion en .net para agregar el CAF desde xml?

    ResponderEliminar
    Respuestas
    1. Estimado, no existe una instrucción que haga eso directamente, debes crear una rutina que extraíga el contenido del CAF sin nodificaciones y lo inserte como nodo al documento DTE. Te recomiendo que lo extraígas utilizando XmlDocument y antes de cargar el CAF en este objeto le indiques PreserveWhiteSpace = true. Eso abre el CAF sin ordenarlo. Que es lo que necesitas para trabajar con el. Si tienes problemas escribeme nuevamente y te envío mas información.

      Eliminar
  2. Estimado, no existe una instrucción que haga eso directamente, debes crear una rutina que extraíga el contenido del CAF sin nodificaciones y lo inserte como nodo al documento DTE. Te recomiendo que lo extraígas utilizando XmlDocument y antes de cargar el CAF en este objeto le indiques PreserveWhiteSpace = true. Eso abre el CAF sin ordenarlo. Que es lo que necesitas para trabajar con el. Si tienes problemas escribeme nuevamente y te envío mas información.

    ResponderEliminar
    Respuestas
    1. te pasaste muchas gracias....pero estoy con una duda que te escriba mas abajo

      Eliminar
  3. firme con la rutina que indicas, pero no se supone (segun recuerdo de la doc. del sii) que los tag (X509Certificate y SignatureValue) deben ser a lo mas de 76 caracteres por linea, lo que a mi me genera es todo en una sola linea???

    ResponderEliminar
    Respuestas
    1. Es verdad pero yo en el tiempo he enviado muchos DTEs con este formato y el SII los acepta sin problemas. Descubrí esto hace varios años y no he tenido problemas. Tambien puedes crear una rutina que ordene el nodo x509certificate. Tambien te funcionará.

      Eliminar
  4. Estimado tengo una duda en el cierre del nodo despues sigue bck8Cq2y6yP86bof2jXc87YZeranEDR8ZMXCmqWTb9iTA6wBSy2G5x3OSNtKu+04Vq8tZ/SL2POlBAmJDYl8+g== esto se casa igual del CAF, lo que pasa que no puedo extraer --algoritmo="SHA1withRSA"-- esta seccion me toma solo el contendo

    ResponderEliminar
  5. Hola marcelo, seguí tu blog desde la web del programador y la verdad me parece excelente que compartas esta información sin ningún afán de lucro, solo me queda una duda, yo programo con clipper 5.2, como puedo generar y conectar al servidor para enviar y recibir todo lo que explicas aquí en tu blog??, no estoy familiarizado con muchos términos que utilizas en verdad. disculpa la ignorancia, te escribo desde México, serán tus términos diferentes por la nación?, aquí no he leído nada igual, saludos!!!

    ResponderEliminar
    Respuestas
    1. Estimado colega,
      Voy a revisar mis documentos y te cuento si puedo ayudarte con tus desarrollos.
      Gracias por tus comentarios.

      Eliminar
  6. marcelo.

    se puede bajar el listado de emisores autorizados??

    ResponderEliminar
    Respuestas
    1. Logan,

      Puedes entrar a la pagina del SII en esta url
      https://palena.sii.cl/cvc/dte/ee_empresas_dte.html
      luego seleccionas los emisores que buscas y le dices consultar.
      El resultado de esta operacion regresará una lista de lo que buscas. Existe un link sobre esta lista que te permitirá descargar el listado completo.

      Espero haberte ayudado.

      Eliminar
    2. si eso lo se, pregunte mal.
      Mi duda es si esta descarga la puedo automatizar?

      Eliminar
    3. La verda es que no tengo información del sii de como hacerlo o si existe un servicio que permita reliazarlo. Creo que no, pero desde el punto de vista programatico solo necesitarias poder realizar una referencia al link de la página de resultado utilizando un objeto request y bajar el resultado a tu maquina.

      Así que si la respuesta es positiva pero requiere desarrollo.

      Eliminar
    4. si en eso estaba... incluso trate de hacer el request a https://palena.sii.cl/cvc/dte/ee_empresas_dte.html simulando los head... me funciona siempre y cuando este en session en el sii. incluso trate de meter el token que tambien va y nada.

      seguire viendo..

      Eliminar
  7. Después de varias pruebas e intentos y muchas tazas de café, pude construir el libro correctamente ,firmarlo y enviarlo (a mano pero enviarlo), funcionando perfectamente según tus recomendaciones y especificaciones.

    Muy agradecido por toda la información y tiempo

    ResponderEliminar
    Respuestas
    1. Estimado,

      Podría contactarse conmigo por favor 62242459

      Muchas gracias

      Eliminar
  8. Marcelo, hace poco nos hiciste una asesoría de la cual estamos muy agradecidos, gracias a ti pudimos enviar sin problemas los DTE y Libros al SII. Recomiendo al 100% tus asesorías, ya que la información sobre este tema es muy escasa y prácticamente todo es plataforma JAVA. Este blog permite a muchos seguir adelante con nuestros proyectos de facturación electrónica, te agradezco enormemente.

    Saludos.

    ResponderEliminar
  9. Buen material, me ha servido bastante se agradece.
    Pero tengo un problema con la firma, el dte lo firmo y luego vuelvo a firmar el set, lo subo a sii y me es rechazado por firma.
    Alguna sugerencia o flujo que debo seguir, incluso cree una nueva rutina de firma con la documentación de microsoft y el resultado es el mismo.

    ResponderEliminar
    Respuestas
    1. Olvidenlo, era error entro teclado y la silla.
      Me funciono perfecto.

      Eliminar
    2. Mauricio,
      Lamento no poder contestar rapidamente, el trabajo me tiene full.

      Que bueno que solucionaste tu problema.

      Eliminar
  10. Marcelo,

    Estamos enviando un archivo XML firmado al SII con respecto a la Cesión electrónica, el cual hemos validado schema y consumo correcto del servicio automático del SII, sin embargo arroja un error "Rechazado por Firma de Sobre". ¿A que se podrá referir con Firma de Sobre?

    ResponderEliminar
    Respuestas
    1. Carlos,

      buenos días, mira lo primero es ver la posibilidad que me envies el documento para verlo y despues puedo comentarte que es lo que podría estar ocurriendo.

      Dejame revisar los formatos de envio de las cesionespara saber si descubro algo.

      Atte.
      Marcelo Rojas R

      Eliminar
    2. Gracias Marcelo.... te envié un correo con el XML.

      Eliminar
    3. Carlos,
      Tengo el mismo error al generar la cesión electrónica. Favor puedes indicarme como solucionaste el problema ?

      Gracias.

      Eliminar
  11. Gracias por compartir esto me ha funcionado bien....cuando envio al sii me da el siguiente error:

    (TED-2-510) Firma Timbre Electronico Incorrecta

    si pudieses guiarme donde tengo el error por favor??

    ResponderEliminar
    Respuestas
    1. Particularmente este error tiene relacion con el timbre del documento, para solucionarlo verifica que el CAF este bien insertado en el documento DTE. Te recomiendo que leas este articulo para que puedas insertar correctamente los datos del CAF. Recuerda que el caf debe ir insertado en el dte sin cambios ni arreglos. aunque se vea feo. No lo ordenes ni corrijas. eso solucionara el problema:

      http://lenguajedemaquinas.blogspot.com/2013/05/ejemplo-timbre-electronico-del-dte.html

      Eliminar
  12. Hola Marcelo, gracias por compartir esta información. Sabes, tengo un problema con respecto a la validación. Estoy en PHP y no logro detectar el problema. La firma de los DD con la private key está OK (de acuerdo al resultado de la doc y el tuyo), el mecanismo de firma con el archivo de certificado también (recupero token sin problemas), el tema es que al generar la firma de DTE y SETDTE si no le coloco la URI me indica "RPR - DTE Aceptado con Reparos (TED-2-510) Firma Timbre Electronico Incorrecta", pero si agrego la URI de acuerdo a los formatos definidos en documentación SII, me indica "RCH - DTE Rechazado (DTE-3-505) Firma DTE Incorrecta (Rechaza DTE)". El CAF lo incorporo obedientemente tal cual, extraigo de archivo, corto el trozo CAF y pego completito, sin tocar ni modificar. La razón social en el caf tiene acento..no se me ocurre qué más podría ser..alguna idea??? Como puedo validar por separado solo el DTE (y no el SETDTE). Gracias.

    ResponderEliminar
    Respuestas
    1. Aclaro que antes de incorporar el CAF saqué todos los espacios como indicas y la carga del XML la realizo con preserveWhiteSpace = TRUE

      Eliminar
    2. Resolví parte con respecto a la URI, pero sigo con Firma Incorrecta. Reviso los archivos con una herramienta y el trozo del CAF es exactamente igual... veo una diferencia en que el archivo CAF está codificado ANSI y el generado en "Western European (Windows)"... tendrá algo que ver?

      Eliminar
    3. Efectivamente debes cambiar la codificacion de recuperación por ISO-8859-1

      Eliminar
  13. Hola Marcelo, muy buen post y totalmente de mucha ayuda, te escribo porque estoy generando el documento y me entrega error "Rechazado por Error en Firma", quite todos los espacios de acuerdo a tus consejos y nada, hay algo que en me puedas orientar, por tu respuesta gracias.

    ResponderEliminar
  14. Recomiendo 100% los servicios de asistencia técnica de Marcelo, conoce muy bien el tema de facturación electrónica y además los problemas y posibles soluciones que van apareciendo, muchas gracias!!!!

    ResponderEliminar
  15. Estimado, una consulta con respecto al armado de DTE en C#.
    de donde se saca el TimeStamp que va en la etiquetas TmstFirmaEnv, TSTED , y TmstFirma ??

    ResponderEliminar
    Respuestas
    1. Estimado,
      los valores de estos nodos deben ser insertados al momento de iniciar el firmado del documento. El fomato del nodo es yyyy-mm-ddThh:mm:ss. Recuerda que este valor debe ser calculado cuando se va a firmar el documento. No funcionara si calculas el valor hoy y firmas mañana.

      Eliminar
    2. Si lo estoy haciendo con un StringBuilder esta bien esto:
      sb.Append("xxxx");

      sb.Append(""+DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss")+"");

      sb.Append("");

      Eliminar
    3. que raro no se publica el texto que va dentro de las llaves "<>" "" pero se entiende?

      Eliminar
    4. No logro entender bien tu problema, si quieres puedes llamame al 24042279

      Eliminar
  16. te puedo enviar un pantallazo a abaddon.1974@gmail.com?? o alguna otra parte??

    ResponderEliminar
  17. Macelo
    Utilizando PreserveWhiteSpace = true no ordena los nodos y se procede a la firma pero despues de firmar como vuelves a ordenar los nodos para subir el dte al sii ya que ellos piden es formato

    ResponderEliminar
    Respuestas
    1. Cesar,
      La verdad es que utilizando PreserveWhiteSpace = true el documento xml es abierto sin realizar ningun tipo de orden sobre los nodos. Al momento de firmarlo lo guardo tal como esta, sin modificaciones pues eso invalidaría la firma. Asi que despues de firmarlo no hago ningun orden sobre el documento y lo envío tal cual.

      Eliminar
    2. Macelo,
      Me podrías ayudar cuando subo el archivo a SII, me arroja un error el la firma.
      te puedo mandar el archivo?? para ver si encuentras algo?

      de ante mano gracias

      Eliminar
  18. Saludos Marcelo.
    Junto con agradecerte esta gran iniciativa que creo q a ayudado a muchos, sobretodos los que usamos C#.
    Es que queria preguntar si tienes algunos tips el "SET de pruebas".
    Por ejemplo:
    - Que Rut se usa, en el XML del DTE, para el supuesto cliente.
    - En la caratula del ENVIO_DTE que datos colocas en y

    A modo de sugerencia seria genial si desarrollaras este punto en algun post.

    ResponderEliminar
  19. Hola Marcelo, oye sabes me da un error de signature cuando intento enviar el dte, mi dte es este:
    https://drive.google.com/file/d/0B3PT3OZNKSszN3ltcDBzVFFxQkk/edit?usp=sharing

    lo extraño es q tengo todo ordenado hasta el momento de la firma, pero la firma se agrega en forma desordenada y es justo ahi donde me tira error. ¿que sera?

    me dice:
    Linea:104 The element type "Signature" must be terminated by the matching end-tag "</Signature>".
    con status 7

    en mi dte esta correctamente cerrado el signature, eso es lo extraño..

    aqui puedes bajar en formato xml:
    https://drive.google.com/file/d/0B3PT3OZNKSszLW9ZRFlIRWlpeUE/edit?usp=sharing

    ResponderEliminar
  20. lo solucione, tuve que agregar la siguiente linea al final de la secuencia:

    secuencia.Append("--7d23e2a11301c4--\r\n");

    esta es una linea de cierre q va despues de agregar envioDTE a la secuencia

    ResponderEliminar
    Respuestas
    1. Kataku, me sirvió tu solución, comparto las líneas original y solucionado:

      Original:
      secuencia.Append("\r");
      secuencia.Append(xdocument.ToString(SaveOptions.DisableFormatting));
      secuencia.Append("\r\n");

      Solucionado:
      secuencia.Append("\r");
      secuencia.Append(xdocument.ToString(SaveOptions.DisableFormatting));
      secuencia.Append("\r\n");
      secuencia.Append("--7d23e2a11301c4--\r\n");

      Eliminar
    2. Gracias!! también me sirvió la solución :)

      Eliminar
  21. Hola Kataku:
    Se que esta pregunta no tiene nada que ver con lo que estás preguntando, pero me gustaría saber como hiciste para firmar, por separado, los nodos SetDoc y el F243096-1?? Yo tengo casi armado mi DTE y no he podido firmar los nodos por separado, a pesar de de haber proporcionado las referencias respectivas.
    Como lo hiciste tu??

    Revisé tu archivo y al compararlo con el archivo de ejemplo "F60T33-ejemplo.xml" se ve que está todo correcto.

    Saludos,
    DanielZ.

    ResponderEliminar
  22. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  23. Cuando firmo me quedan las dos, por debajo de"/ SetDTE " y por sobre "/ EnvioDTE "
    Algo ocurre y algo estoy haciendo mal.

    Gracias por algún consejo.

    ResponderEliminar
  24. Hola Marcelo Rojas:

    En primer lugar, deseo expresar mis agradecimientos por la valiosa e interesante información de su blog, me ha sido de gran utilidad.

    Lo segundo, tiene que ver unas consultas sobre el archivo EnvioDTE.xml, sobre el cual ya he logrado insertar :

    Caratula, Encabezado, Detalles, CAF y el timbre, el cual se obtiene, como ya lo ha mencionado, al computar DD + La clave privada del CAF.

    También he logrado firmar el archivo pero tengo dos consultas al respecto.
    a. Entiendo que se debe firmar el nodo "EnvioDTE" y también el nodo interno DTE.
    Hasta el momento he firmado el primer nodo (nodo raíz) y me faltaría el DTE.
    ¿Cómo lo hago? en la referencia coloco "F60T33" pero al ejecutarlo necesariamente, me firma el SetDTE.. algo estoy haciendo mal pero no se que puede ser.

    Desde ya agradezco si fuese posible tu orientación al respecto.

    De antemano gracias.

    ResponderEliminar
  25. Hola,
    Recibí del SII el mensaje: "RFR - Rechazado por Error en Firma"
    Alguien sabe a qué firma se refiere? EnvioDTE, DTE, TED?

    Gracias,
    JC

    ResponderEliminar
    Respuestas
    1. Hola, tengo el mismo problema (en PHP) lograste solucionarlo?

      Eliminar
  26. Estoy con el mismo problema de la firma y les comento lo que he hecho hasta ahora:

    - Al codificar a ISO-8859-1, sólo cambia el caracter '&' a '&', pero esto no me cambia las tildes.
    - He intentado cambiar las tildes a mano, reemplazando 'á' por 'á' y tambien 'á' por 'á', pero la codificación ISO-8859-1 me vuelve a reemplazar el caracter '&' dejando '&aacute;' y '&#225;'.
    - También he quitado los acentos, reemplazo 'á' por 'a' y el servicio me lo acepta sin problemas, pero al declarar avance, me responde que el ítem que devería llevar acento, no es lo que se esperaba.

    Gracias.

    ResponderEliminar
    Respuestas
    1. Solucionado,

      Luego de hablar con Marcelo (gracias por tu disposición), me indica que en el método para generar la firma del timbre, hay que cambiar lo siguiente:

      Antes:
      ASCIIEncoding ByteConverter = new ASCIIEncoding();

      Ahora:
      Encoding ByteConverter = Encoding.GetEncoding("ISO-8859-1");

      Esto, porque ASCIIEncoding no toma en cuenta las tildes.

      referencia al método para generar la firma del timbre: http://lenguajedemaquinas.blogspot.com/2013/05/ejemplo-timbre-electronico-del-dte.html

      Eliminar
  27. Hola Marcelo,

    Estoy desarrollando en PHP con Symfony2 la firma de los DTE. Avancé sin mayores problemas hasta el momento de enviar al SII el XML firmado. Envío el xml y siempre recibo "RFR - Rechazado por Error en Firma". He tratado de firmar de formas distintas el documento pero consigo el mismo resultado. Será que el xml necesita algún formato particular? todo a la izquierda? El digest de la firma se debe calcular de afuera hacia adentro, es decir, primero calculo el digest para el envío (SetDTE), luego el digest para cada documento (Documento)?

    Actualmente para firmar lo que hago es usar las funciones de php para openssl y lo aplico en el orden: Documento (canonizado) -> firma -> SetDTE (canonizado) -> firma.

    Si pudieras darme algun tips o ayuda con respecto al porque o a las posibles causas del error RFR te lo agradecería.

    Saludos y gracias

    ResponderEliminar