luisgoncalves / xades4j

A Java library for XAdES signature services
GNU Lesser General Public License v3.0
109 stars 65 forks source link

Help on XAdes-EPES for Colombian IRS (DIAN) #134

Closed pedroAOO closed 6 years ago

pedroAOO commented 6 years ago

Hi Luis,

We're trying to certificate as a voluntary electronic invoice issuer with the Colombian IRS (DIAN). One of the requirement is the generation of XML signed with XAdes-EPES [plus some locally defined additions]. I'm looking at this library [xades4j], particularly SignerEPESTest.java and the information in the wiki. It seems just what I'm looking for, but I've some time constraints and I would ask if you offer your professional services to develop the applicaction I need [ XML file + Digital Certificate ==> XAdes-EPES signed XML file] (with the specifications given by Colombian DIAN).

Thanks in advance

luisgoncalves commented 6 years ago

Hi @pedroAOO

I currently don't work as a freelancer., but I can try to help you define the requirements and point in the right direction. For instance:

edennish commented 6 years ago

Hi Luis,

I'm writing from Costa Rica, just as Pedro I need to sign an XML (electronic invoice) for the Treasury Department in Costa Rica.

My requirements are:

We don't use smart cards instead we need to apply a certificate given by the Treasury Department.

I found your library and I would like to know if I can use it to do the job. I know that cryptography is a big topic and I'm just a beginner in it, it is a shame that you don't work as a freelancer.

Can you orient me about what I need to develop a class that uses your library and accomplishes my requirement? I'm trying your SignerTestBase class to extract the logic, but I have some issues (SignerEPES is not public in xades4j.production; cannot be accessed from outside package).

Thanks in advance for any help you can bring me. Best regards,

Erick Dennis.

luisgoncalves commented 6 years ago

Hi Erick,

From what you said, it seems totally possible to use xades4j. Here are a few notes that may help you:

DataObjectDesc obj = new DataObjectReference("#<id-of-parent-element>")
       .withTransform(new EnvelopedSignatureTransform());

Let me know if I can be of further help.

edennish commented 6 years ago

Hi Luis,

Thanks for your answer.

I'm trying to follow your indications, but I think I'm having problems with the FileSystemKeyStoreKeyingDataProvider class, I implemented two classes just as you did in the test:

First:

public class FirstCertificateSelector implements SigningCertSelector
{
    @Override
    public X509Certificate selectCertificate(
            List<X509Certificate> availableCertificates)
    {
        return availableCertificates.get(0);
    }
}

And:

public class DirectPasswordProvider implements KeyStoreKeyingDataProvider.KeyStorePasswordProvider,
KeyStoreKeyingDataProvider.KeyEntryPasswordProvider {
 private char[] password;

    public DirectPasswordProvider(String password)
    {
        this.password = password.toCharArray();
    }

    @Override
    public char[] getPassword()
    {
        return password;
    }

    @Override
    public char[] getPassword(String entryAlias, X509Certificate entryCert)
    {
        return password;
    }
}

And in the main class I wrote:

        kp = new FileSystemKeyStoreKeyingDataProvider(
                   "pkcs12", 
                   options.valueOf("certificate").toString(),
                   new FirstCertificateSelector(), 
                   new DirectPasswordProvider(options.valueOf("password").toString()),
                   new DirectPasswordProvider(options.valueOf("password").toString()), 
                   false);

When I run the class the result is:

[main] INFO com.alfasol.firmaxml.Main - Inicio [main] INFO com.alfasol.firmaxml.Main - Llamado de Funcion signXML [main] INFO com.alfasol.firmaxml.Main - Inicio de Funcion signXML [main] INFO com.alfasol.firmaxml.Main - Policy Provider [main] INFO com.alfasol.firmaxml.Main - Key Store Data Provider. Certif: C:\opt\FirmaXML\test\certfile.p12 [main] INFO com.alfasol.firmaxml.Main - Password: XXXXXX [main] INFO com.alfasol.firmaxml.Main - Xades EPES Signing Profile [main] INFO com.alfasol.firmaxml.Main - XML Document: C:\opt\FirmaXML\test\test.xml [main] INFO com.alfasol.firmaxml.Main - Sign XML

xades4j.verification.UnexpectedJCAException: The keystore couldn't be initialized at xades4j.providers.impl.KeyStoreKeyingDataProvider.ensureInitialized(KeyStoreKeyingDataProvider.java:179) at xades4j.providers.impl.KeyStoreKeyingDataProvider.getSigningCertificateChain(KeyStoreKeyingDataProvider.java:189) at xades4j.production.SignerBES.sign(SignerBES.java:158) at xades4j.production.SignerBES.sign(SignerBES.java:129) at xades4j.production.Enveloped.sign(Enveloped.java:68) at com.alfasol.firmaxml.Main.signXML(Main.java:153) at com.alfasol.firmaxml.Main.main(Main.java:96) Caused by: java.security.KeyStoreException: KeyStore instantiation failed at java.security.KeyStore$Builder$FileBuilder.getKeyStore(Unknown Source) at xades4j.providers.impl.KeyStoreKeyingDataProvider.ensureInitialized(KeyStoreKeyingDataProvider.java:175) ... 6 more Caused by: java.io.IOException: keystore password was incorrect at sun.security.pkcs12.PKCS12KeyStore.engineLoad(Unknown Source) at java.security.KeyStore.load(Unknown Source) at java.security.KeyStore$Builder$FileBuilder$1.run0(Unknown Source) at java.security.KeyStore$Builder$FileBuilder$1.run(Unknown Source) at java.security.KeyStore$Builder$FileBuilder$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) ... 8 more Caused by: java.security.UnrecoverableKeyException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded ... 14 more

I have some concerns, the first is that I saw an example of a service provider of XML Sign (here in Costa Rica) and they don't use a password for the signing, the provider uses a user id, application id, but not a password. Is this possible? Do I need to establish another class with those parameters?

I really appreciate your help and ask your pardon if my questions are dumb, but I don't fully understand how this signing process works.

Best regards.

luisgoncalves commented 6 years ago

@edennish:

pedroAOO commented 6 years ago

Hi Luis,

Thanks for your answer, i've prepared the information

We signed an XML document (using xades4j) and sent to DIAN for verification, but it was rejected with the following message :

 com.indra.mmdd.signature.exceptions.ValidateException:

xades4j.verification.ReferenceValueException: Reference '#xmldsig-5f8be9a8-2cc7-482a-ad53-281caece0ad3-keyinfo' cannot be validated

I've atached the signed document and the java source we are using, if you can help me to get a good signed document I'll be very grateful,

Thanks in advance.

Pedro.

2017-12-03 9:01 GMT-03:00 Luís Gonçalves notifications@github.com:

Hi @pedroAOO https://github.com/pedroaoo

I currently don't work as a freelancer., but I can try to help you define the requirements and point in the right direction. For instance:

  • How's the signing certificate obtained? I'm assuming it is some sort of smart card integrated in the government authentication infrastructure. Is this correct? Is it a PKCS#11 card?
  • If I understood correctly, the input to be signed is an invoice in XML. How should the resulting signature be stored? Should it be appended to the existing XML document? Or a standalone file?
  • What other "locally defined additions" are at stake? Specific combinations of already supported qualifying properties? Or something else?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/luisgoncalves/xades4j/issues/134#issuecomment-348759328, or mute the thread https://github.com/notifications/unsubscribe-auth/AgjUHK2JVaNBGTRo7EwEpii0xPT89kgVks5s8o2fgaJpZM4Qwqvc .

FuriosoJack commented 6 years ago

@pedroAOO podrias dejar ver la política yo tuve el mismo problema y era eso

luisgoncalves commented 6 years ago

@pedroAOO,

I think the attachments didn't go through, as you replied to GitHub by email. Can you paste the relevant code in the issue or upload it somewhere?

You probably already have something working, but the notes I left on the comment above for Erik also apply to your scenario.

pedroAOO commented 6 years ago

Luis, here are the files. Please change the extension to rar (txt --> rar) [rar and xml where not supported to upload] Firma_EPES_rar.txt (Content of rar : Factura_firmada.xml source.java; password : 12345)

The Policy and Role are generated correctly (apparently)

luisgoncalves commented 6 years ago

@pedroAOO Since you closed the issue, I'm not sure if you managed to fix everything. Anyway, looking at your files, I have the following notes:

The rest of the code and resulting signature looks good..

pedroAOO commented 6 years ago

Sorry, but it was not my intention to close the issue (I think I was sending the comment). I'm reopening it, because I stil have the problem.

I'll analize your advices and try to put on my program.

Thanks for your help, and I apologize again for the unintended close

edennish commented 6 years ago

Hi Luis,

I was able to sign an XML, now I'm working on the validation process. By the way, the Treasury Department accepted the sign. Thanks for your help.

Pedro, una de las cosas que hice con las politicas, fue revisar el ejemplo del XML que daba tributación en CR, para asegurarme que tuviera el mismo formato y tags , despues lo que hice fue ajustar el ObjectIdentifier para que el resultado fuera el esperado.

Esto fue lo que utilice: SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() { public SignaturePolicyBase getSignaturePolicy() { return new SignaturePolicyIdentifierProperty( new ObjectIdentifier("https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica"), new ByteArrayInputStream("Politica de Factura Digital".getBytes())); } };

Mucha suerte!

osgroupCR commented 6 years ago

Hola @edennish, también te escribo desde Costa Rica y estoy realizando el mismo proceso para la facturación electronica, inicié con la firma XADES en PHP usando OpenSSL y curl y un juego de procesos pero es muy expuesto a errores los cuales se dieron con la versión 4.2 de Hacienda. Podrías compartir el código con el cual resolviste los requerimientos de hacienda usando xades4j? De antemano muchas gracias.

edennish commented 6 years ago

Hola, parece que estamos corriendo contra el tiempo :) este el el codigo del prototipo que usé para probar la firma:


static void signXML(OptionSet options) {
        slf4jLogger.info("Inicio de Funcion signXML");

        KeyingDataProvider kp;

        slf4jLogger.info("Policy Provider");
        try {

            SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
                public SignaturePolicyBase getSignaturePolicy() {
                    return new SignaturePolicyIdentifierProperty(
                            new ObjectIdentifier("https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica"),
                            new ByteArrayInputStream("Politica de Factura Digital".getBytes()));
                }
            };

            slf4jLogger.info("Key Store Data Provider. Certif: {}", options.valueOf("certificate").toString());
            //slf4jLogger.info("Password: {}", options.valueOf("password").toString());
            slf4jLogger.info("Password: {}", options.valueOf("password").toString());

            kp = new FileSystemKeyStoreKeyingDataProvider(
                       "pkcs12", 
                       options.valueOf("certificate").toString(),
                       new FirstCertificateSelector(), 
                       new DirectPasswordProvider(options.valueOf("password").toString()),
                       new DirectPasswordProvider(options.valueOf("password").toString()), 
                       false);

            slf4jLogger.info("Xades EPES Signing Profile");

            // SignaturePolicyInfoProvider spi = new
            XadesSigningProfile p = new XadesEpesSigningProfile(kp, policyInfoProvider);
            //p.withBasicSignatureOptionsProvider(new SignatureOptionsProvider());

            slf4jLogger.info("XML Document: {}", options.valueOf("input").toString());

            // open file
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = null;
            builder = factory.newDocumentBuilder();
            Document doc1 = builder.parse(new File(options.valueOf("input").toString()));
            Element elemToSign = doc1.getDocumentElement();

            // sign whole document
            slf4jLogger.info("Sign XML");

            XadesSigner signer = p.newSigner();
            //SignerEPES signer = (SignerEPES)p.newSigner();

            new Enveloped(signer).sign(elemToSign);

            // save output file

            slf4jLogger.info("Transform. Output: {}", options.valueOf("output").toString());

            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            Result output = new StreamResult(new File(options.valueOf("output").toString()));
            Source input = new DOMSource(doc1);

            transformer.transform(input, output);

            slf4jLogger.info("End");
          //KeyStoreException 
        } catch (KeyStoreException | ParserConfigurationException | SAXException | IOException | XAdES4jException | TransformerException e) {

            e.printStackTrace();
        }
    }

Mucha suerte!

vsecades commented 6 years ago

@luisgoncalves thanks for the excellent work. Saved us from having to do this from scratch.

@edennish a small question, I noticed that in order to access the p12 file via a PKCS12 keystore, a password is requested. The p12 certs from Hacienda don't seem to provide one? Are these supposed to be empty strings?

luisgoncalves commented 6 years ago

@vsecades you can pass null on the parameter for the "keystore password provider".

luisgoncalves commented 6 years ago

@pedroAOO Did you manage to produce the signature? Note that @edennish left some additional comments/code that might help you.

pedroAOO commented 6 years ago

Hi Luis,

I implemented your recomendations and the advices from @edennish and today (finally) we get the certification from DIAN (200 consecutives documents signed and verified) :-)

Thanks all for the help, I really apprecite your advices. @luisgoncalves and @edennish I'm very gratefull for your help.

This is the last version of the signing function

private static void signEpes() throws Exception {
    Document doc = null;

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder db = dbf.newDocumentBuilder();
    doc = db.parse(new File(DOCUMENT));

    Element elem = doc.getDocumentElement();
    DOMHelper.useIdAsXmlId(elem);

    KeyingDataProvider kdp = new FileSystemKeyStoreKeyingDataProvider( "pkcs12",
                        CERT_FOLDER + CERT,
                        new FirstCertificateSelector(),
                        new DirectPasswordProvider(PASS),
                        new DirectPasswordProvider(PASS),
                        true);

    // politica
    SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
        @Override
        public SignaturePolicyBase getSignaturePolicy() {
            try {
                return new SignaturePolicyIdentifierProperty(
                        new ObjectIdentifier("http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf", 
                                             IdentifierType.URI, 
                                             "Política de firma para facturas electrónicas de la República de Colombia"),
                        new ByteArrayInputStream(Files.readAllBytes(Paths.get(POLICY)))
                );
            } catch (IOException ex) {
                Logger.getLogger(FirmaFec.class.getName()).log(Level.SEVERE, null, ex);
            }
            return null;
        }
    };

    // Role
    SignerEPES signer = (SignerEPES) new XadesEpesSigningProfile(kdp, policyInfoProvider)
               .withSignaturePropertiesProvider(new SignaturePropertiesProvider() {
                   @Override
                   public void provideProperties(SignaturePropertiesCollector arg0) {
                       SigningTimeProperty sigTime = new SigningTimeProperty();
                       arg0.setSignerRole(new SignerRoleProperty().withClaimedRole("supplier"));
                       arg0.setSigningTime(sigTime );
                   }
               })
          .newSigner();

   new Enveloped(signer).sign(elem);
   TransformerFactory tFactory = TransformerFactory.newInstance();
   Transformer transformer = tFactory.newTransformer();
   DOMSource source = new DOMSource(doc);
   StreamResult result = new StreamResult(new File(SIGNED));

   transformer.transform (source, result);

}

luisgoncalves commented 6 years ago

Nice!

Close the issue if that's it for now. Thanks.

On 20 Dec 2017 20:27, "pedroAOO" notifications@github.com wrote:

Hi Luis,

I implemented your recomendations and the advices from @edennish https://github.com/edennish and today (finally) we get the certification from DIAN (200 consecutives documents signed and verified) :-)

Thanks all for the help, I really apprecite your advices. @luisgoncalves https://github.com/luisgoncalves and @edennish https://github.com/edennish I'm very gratefull for your help.

This is the last version of the signing function

private static void signEpes() throws Exception { Document doc = null;

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(new File(DOCUMENT));

Element elem = doc.getDocumentElement();
DOMHelper.useIdAsXmlId(elem);

KeyingDataProvider kdp = new FileSystemKeyStoreKeyingDataProvider( "pkcs12",
                    CERT_FOLDER + CERT,
                    new FirstCertificateSelector(),
                    new DirectPasswordProvider(PASS),
                    new DirectPasswordProvider(PASS),
                    true);

// politica
SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
    @Override
    public SignaturePolicyBase getSignaturePolicy() {
        try {
            return new SignaturePolicyIdentifierProperty(
                    new ObjectIdentifier("http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf",
                                         IdentifierType.URI,
                                         "Política de firma para facturas electrónicas de la República de Colombia"),
                    new ByteArrayInputStream(Files.readAllBytes(Paths.get(POLICY)))
            );
        } catch (IOException ex) {
            Logger.getLogger(FirmaFec.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
};

// Role
SignerEPES signer = (SignerEPES) new XadesEpesSigningProfile(kdp, policyInfoProvider)
           .withSignaturePropertiesProvider(new SignaturePropertiesProvider() {
               @Override
               public void provideProperties(SignaturePropertiesCollector arg0) {
                   SigningTimeProperty sigTime = new SigningTimeProperty();
                   arg0.setSignerRole(new SignerRoleProperty().withClaimedRole("supplier"));
                   arg0.setSigningTime(sigTime );
               }
           })
      .newSigner();

new Enveloped(signer).sign(elem); TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File(SIGNED));

transformer.transform (source, result);

}

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/luisgoncalves/xades4j/issues/134#issuecomment-353173781, or mute the thread https://github.com/notifications/unsubscribe-auth/ADyghWKD_HIeFwzPM5BOaoyah36IwZW6ks5tCW3CgaJpZM4Qwqvc .

pedroAOO commented 6 years ago

Thanks all, I'm closing the issue.

ghost commented 6 years ago

Hello @pedroAOO ! Thanks for sharing, could you please give some information about how you got the certificate, the type of certificate and the cost of it for Colombian case? Just like the CA you used for the signature process, thank you!

jrodriguezj88 commented 6 years ago

Hola @edennish !

En la parte de SignaturePolicyIdentifierProperty ¿esos valores que estás usando son válidos? Usando tu ejemplo firmo el documento pero aún así Hacienda CR me retorna que la firma no es válida. Tengo un ejemplo en C# funcionando con parámetros: "https://tribunet.hacienda.go.cr/docs/esquemas/2016/v4.1/Resolucion_Comprobantes_Electronicos_DGT-R-48-2016.pdf" y Digest "NmI5Njk1ZThkNzI0MmIzMGJmZDAyNDc4YjUwNzkzODM2NTBiOWUxNTBkMmI2YjgzYzZjM2I5NTZlNDQ4OWQzMQ=="

Adjunto el código test que estoy utilizando que me retorna como no válida:

public class java extends SignatureServicesTestBase {
    public static void main (String[] args) throws Exception {
        try {
        System.out.println("Aqui empieza el codigo");
    //establezco la politica de firma
        SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
            public SignaturePolicyBase getSignaturePolicy() {
                return new SignaturePolicyIdentifierProperty(
                        new ObjectIdentifier("https://tribunet.hacienda.go.cr/docs/esquemas/2016/v4.1/Resolucion_Comprobantes_Electronicos_DGT-R-48-2016.pdf"),
                        Base64.getDecoder().decode("NmI5Njk1ZThkNzI0MmIzMGJmZDAyNDc4YjUwNzkzODM2NTBiOWUxNTBkMmI2YjgzYzZjM2I5NTZlNDQ4OWQzMQ=="));
            }
        };

        //ingreso la información de los certificados
        KeyingDataProvider kp = new FileSystemKeyStoreKeyingDataProvider(
                "pkcs12",
                "/../Certificado.p12",
                new FirstCertificateSelector(),
                new DirectPasswordProvider("clave"),
                new DirectPasswordProvider("clave"),
                true);

        //crea el perfil de firma xades
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder = null;
        builder = factory.newDocumentBuilder();
        Document doc1 = builder.parse(new File("factura.xml"));
        Element elemToSign = doc1.getDocumentElement();
        XadesSigningProfile p = new XadesEpesSigningProfile(kp, policyInfoProvider);
        XadesSigner signer = p.newSigner();    
        new Enveloped(signer).sign(elemToSign);
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        Result output = new StreamResult(new File("firmado.xml"));
        Source input = new DOMSource(doc1);
        transformer.transform(input, output);

        System.out.println("documento creado");
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}

Saludos, Javier Rodriguez

edennish commented 6 years ago

Hola Javier, si son válidos, llevo más de 100 facturas firmadas y enviadas a hacienda, sin problemas de recepción. Ahora estoy usando el sandbox aun no en producción espero que en producción siga igual.

El código que puse e n este mismo foro es el que uso, exactamente ese.

Muchas suerte!

vsecades commented 6 years ago

Buenas tardes @edennish ,

Gracias por la respuesta -> Estamos en el mismo bote creo. Quería saber si el .p12 que recibes de hacienda le haces algún pre-tratamiento antes de leerlo para pasarlo a la librería?

Veo que pasas un objeto de options, que de este:

options.valueOf("certificate").toString()

Este certificate en que formato lo estás pasando?

Gracias de antemano, Valentín

edennish commented 6 years ago

Hola, esa es la dirección donde esta el archivo en el file system.

Se ocupa el certificado y el pin (password). Si funciona!

Suerte con eso.

edennish commented 6 years ago

Por cierto Javier, al inicio a mi me daba un error de firma del xml pero era por los namespaces. Revisa que eso este como lo pide hacienda, incluyendo minúsculas y mayúsculas. Supongo que la descripción del error de hacienda estaba mala. Suerte.

jrodriguezj88 commented 6 years ago

@edennish acabo de lograrlo muchísimas gracias! el namespace del documento debe ser el mismo del SignaturePolicyIdentifierProperty.

dcortes22 commented 6 years ago

@edennish estoy tratando de lograr una firma correcta, como hizo para agregar el not(ancestor-or-self::ds:Signature) y el application/octet-stream aun utilizando su mismo codigo la firma me sale q no es valida

dcortes22 commented 6 years ago

@jrodriguezj88 podria indicarme en que momento agrega el namespace? es antes o después del fimado

jrodriguezj88 commented 6 years ago

@dcortes22, No hay necesidad de esto not(ancestor-or-self::ds:Signature) ni application/octet-stream, el código funciona como lo presentó @edennish . El namespace al que que me refiero es al del tag de FacturaElectronica que tiene que ser el mismo que el de la política y tiene que estar presente antes del firmado. <FacturaElectronica xlmns="https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica"...

Suerte.

cgranados16 commented 6 years ago

Hola! Estoy usando el código de @edennish pero cada vez que envió la respuesta que me da Hacienda es

La firma del comprobante electrónico no es válida

El documento tiene la política en el tag de FacturaElectronica. La verdad no tengo idea si algo se me está yendo del formato del XML. Adjunto un "ejemplo" de el documento que estoy firmando y enviando a Hacienda. Muchas gracias. FacturaElectronica_Ejemplo_xml.txt

dcortes22 commented 6 years ago

@cgranados16 yo estoy teniendo el mismo problema, además estaba verificando la firma y veo que hay caracteres extraños en los algoritmos SHA (https://user-images.githubusercontent.com/1170942/34645989-1c9b70e2-f322-11e7-800b-42232c606d41.png)

Alguno le ha pasado esto?

mauroooooooo commented 6 years ago

@cgranados16 @dcortes22 @edennish @jrodriguezj88 Buenas!!! yo ya tenia documentos aprobados en noviembre del año pasado y habia dado por terminado el tema de la firma y demas, ahorita estoy retomando y tirando unas pruebas y me tira siempre error de la firma, mi codigo para firmar estaba un poco diferente al de @edennish porque incluso usaba otra liberia, hice el cambio solo para probar y sigo con el mismo error, podrian compartirme el encabezado solo por aquello de que tenga algo diferente y que sea eso mas bien.

Gracias por cualquier apoyo que me puedan dar

dcortes22 commented 6 years ago

buenas estimados compañeros después de mucho debbugear les comento tengan cuidado con el signature date asegúrense que sea en la fecha de hoy por qué si no si firma será inválida

mauroooooooo commented 6 years ago
2018-01-09T11:21:32.166-06:00 Me parece que eso si esta bien
dcortes22 commented 6 years ago

y cuál librería usa? otro dato es que xades4j 1.4 no está funcionando asegúrese de usar 1.3.2

mauroooooooo commented 6 years ago

Si estaba con la 1.4, pero pase a la 1.3.2 y sigue el problema :( ud no tiene el encabezado para ver que no lo tenga diferente? el del ultimo documento aprobado que tuve estaba este

xmlns="https://tribunet.hacienda.go.cr/docs/esquemas/2016/v4.1/facturaElectronica" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://tribunet.hacienda.go.cr/docs/esquemas/2016/v4.1/facturaElectronica https://tribunet.hacienda.go.cr/docs/esquemas/2016/v4.1/FacturaElectronica..xsd"

dcortes22 commented 6 years ago

ohh dato interesante metase a hacienda ya está la versión 4.2 cambie ese encabezado

jesusrodriguezm commented 6 years ago

@dcortes22 si el encabezado debe llevar la fecha del día actual, para el caso en que esté caído el servidor de hacienda, y se envién los comprobantes después (podría cambiarse de día), hay que volver a firmarlos justo antes de cada envío. ¿no?

roy1196 commented 6 years ago

@edennish utilice el código que publicastes, pero a pesar de todo Hacienda me no me acepta la firma generada, puedes ayudarme con eso por favor? de paso agradecerte por el aporte.

edennish commented 6 years ago

Hola, revisa el namespace del xml. Podría ser eso!

jesusrodriguezm commented 6 years ago

@edennish yo estoy igual que @roy1196 ("La firma del comprobante electrónico no es válida") al firmar cambia el orden de 2 de las etiquetas del encabezado. He validado ambos XML contra sus XSD y ambos se validan correctamente.

No firmado: <FacturaElectronica xmlns="https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">

Firmado: <FacturaElectronica xmlns="https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" xmlns:xs="http://www.w3.org/2001/XMLSchema">

Creo que eso está bien.

He visto algunos campos de la firma que son diferentes a los del ejemplo que suministró hacienda (En el documento de "Anexos y estructuras v4.2"). A lo mejor tenemos ahí el problema.

Acabo de ver que el servicio de validacion "https://api.comprobanteselectronicos.go.cr/recepcion-sandbox/v1/recepcion/5..." devuelve el XML con el namespace 4.1.

Además, el servicio de obtener comprobante "https://api.comprobanteselectronicos.go.cr/recepcion-sandbox/v1/comprobantes/5..." me devuelve un error 404

edennish commented 6 years ago

Hola, yo estoy enviando para la factura:

<FacturaElectronica 
    xmlns="https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica" 
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/facturaElectronica.xsd">

Pero igual he tenido muchos problemas con el namespace, porque ocasionalmente Hacienda medice que no encuentra el tag.

Suerte

jesusrodriguezm commented 6 years ago

@edennish muchas gracias por tu ayuda. A ver si conseguimos arreglar los errores los demás.

No se si he avanzado, o he retrocedido, ya no me dice que la firma sea incorrecta, ahora dice esto:

-60, "El contribuyente que firma la factura electronica no es el emisor."

Supongo que eso significa que la firma ya le gusta... pero el emisor SI es el cotribuyente que firma la factura... ¿os pasado a alguno?

¡Gracias!

mauroooooooo commented 6 years ago

@jesusrodriguezm sera que ud me puede ayudar para llegar a ese punto? y yo le ayudo a avanzar con esos errores, yo ya tenia firma valida hace mucho pero por un ajuste me dejo de funcionar

dcortes22 commented 6 years ago

Jesus Rodriguez, eso es que probablemente está agregándole los ceros (0) al inicio de la cédula del emisor, yo hice eso (que aunque así lo dice la documentación que hay que hacerlo) no es válido ya que el certificado no tiene dichos ceros

jesusrodriguezm commented 6 years ago

@mauroooooooo tiene parte del código en este enlace y el resto en el código de @edennish aquí aquí

jesusrodriguezm commented 6 years ago

Acabo de conseguir firmar bien mis primeras facturas. Elimino comentarios anteriores.

Mucho cuidado con el formato de las fechas, hay veces que deben terminar en "...-0600" y otras en "...-06:00". Todo viene indicado en el documento "ANEXOS Y ESTRUCTURAS_V4.2.pdf", al igual que el formato para los números de identificación.

Se puede realizar siguiendo los datos de este comentario.

Muchas gracias a todos por la ayuda, especialmente a @edennish.

@luisgoncalves great library. As you can see there are different countries in LATAM where your library is killing it.

luisgoncalves commented 6 years ago

@jesusrodriguezm thanks 👍 I should start a list of people/companies/projects using the library to use as advertising..

BTW, if anyone has feedback on the existing features/API/internals, specially for advanced scenarios (e.g. extended forms), please bring it on!

lvillamar commented 6 years ago

hola @pedroAOO , como me podria comunicar contigo. saludos mi email es lvillamar@gmail.com