node-saml / xml-crypto

Xml digital signature and encryption library for Node.js
MIT License
198 stars 171 forks source link

Reference to a namespace #168

Closed antoniowd closed 4 years ago

antoniowd commented 5 years ago

Hi, I have a doubt. How can I reference the tag with the xpath?

`<?xml version="1.0"?> <Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2">

2.1 2.0 0101 F002-69 2019-01-15 12:02:85 2019-03-15 01 PEN F002-69 20155523658 #F002-69 20155523658 20155523658 20155523658 PE 12345678 12345678 12345678 123652 PE false 00 0.00 0.00 0.00 15.25 84.75 15.25 S 1000 IGV VAT 84.75 100 0 0 100 1 12 30 3.2 01 20.4 38.400000000000006 20.4 S 18.00 35 1000 IGV VAT 524413 2.5 ` and this is my code 'const pfx = fs.readFileSync('./beta.pfx'); pem.readPkcs12(pfx, {p12Password: '123456'}, (err, pem) => { if (err) { console.log(err); return; } const transforms = [ 'http://www.w3.org/2000/09/xmldsig#enveloped-signature', ]; const infoProvider = (pem) => { return { getKeyInfo() { const cert = this.getCert(); return `${cert}`; }, getCert() { const certLines = pem.cert.split('\n'); return certLines.filter((e, i) => i && e && e.indexOf('-----') !== 0). join(''); }, }; }; let sig = new SignedXml(); sig.addReference( '//*[local-name(.)=\'ExtensionContent\' and namespace-uri(.)=\'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2\']', transforms); sig.signingKey = pem.key; sig.canonicalizationAlgorithm = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'; sig.keyInfoProvider = infoProvider(pem); sig.computeSignature(xml, {prefix: 'ds', attrs: {Id: 'SignatureSP'}}); fs.writeFileSync('./signed.xml', sig.getSignedXml()); ' Everything works fine but I can not make the signature inside that tag. Thanks
dfloresgonz commented 5 years ago

Hello! This might help you: sig.computeSignature(xml, { location: { reference: "//*[local-name(.)='ExtensionContent']", action: "prepend" }, prefix: 'ds', attrs: {Id: 'SignatureSP'} });

Compatriota también estas implementando F.E. en nodejs? podemos ayudarnos!

antoniowd commented 5 years ago

Hi Diego. After trying some variants I found the solution. It's exactly as you say. En efecto estoy haciendo una version de FE en node.js. Como podemos hablar mas?

dfloresgonz commented 5 years ago

por hangouts? dfloresgonz@gmail.com por alli compartimos num_celular

kamilml commented 5 years ago

@tonitim13 @dfloresgonz compatriotas estoy atorado a ver si a uds les ha pasado firmo mi xml y cuando lo envío a la SUNAT me responde esto:

<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <soap-env:Header/>
    <soap-env:Body>
        <soap-env:Fault>
            <faultcode>soap-env:Client.2335</faultcode>
            <faultstring>El documento electr&#243;nico ingresado ha sido alterado - Detalle: Incorrect reference digest value</faultstring>
        </soap-env:Fault>
    </soap-env:Body>
</soap-env:Envelope>

en mi xml firmado hay algunas cosas que son diferentes a lo que deberían, por ejemplo en tag

<ds:Reference URI="#_0">

debería ser <ds:Reference URI="">

Hay otras diferencias (comparo con un comprobante que sí pasa la validación) como el ds:X509Certificate que está como que separado en partes y creo que debería ser un string. También está el <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SignatureSP"> que debería tener solo Id y <ext:ExtensionContent Id="_0"> que NO debería tener Id https://i.imgur.com/aDAZz9i.png

EDIT:---------------------- arreglé lo del <ds:Reference URI=""> 😃 lo demás sigue igual y sigo con el mismo error 😢

dfloresgonz commented 5 years ago

@kamilml Puedes enviar tu xml que es rechazado?

acporras commented 5 years ago

Hola tengo el mismo problema, al generar mi documento se realiza el firmado pero la respuesta es: El documento electrónico ingresado ha sido alterado - Detalle: Incorrect reference digest value

Este es mi documento XML:

`<?xml version='1.0' encoding='UTF-8'?>

IaFoXhFkRLLSGces5OXPZ5eHa98=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 2.1 2.0 F001-1 2017-05-14 15:42:20 2017-05-15 01 SETENTA Y UN MIL TRESCIENTOS CINCUENTICUATRO Y 99/100 PEN 1 F001-245 02 F001-245 20100454523 LlamaSign 20600695771 LLAMA.PE SA #SociallazySign 20553510661 LLAMA.PE SA LLAMA.PE SA 0001 20000000001 TU CLIENTE SAC F001-245 51731.2 2017-05-11 10:42:20 7891.2 43840.00 7891.2 S 1000 IGV VAT 51731.2 0.00 1 2000 43840.00 38.00 01 7891.2 43840.00 7891.2 S 18.00 10 1000 IGV VAT Cerveza Clásica x 12 bot. 620 ml. 21.92 ` Mi codigo de firmado es el siguiente: const pfx = fs.readFileSync(`${Config.certificate}/cert.pfx`); pem.readPkcs12(pfx, { p12Password: "325Darkone" }, (err, cert) => { let certificate = cert; let xmlinvoice = js2xmlparser.parse("Invoice", invoice, { "declaration": { "encoding": "UTF-8" } }) var name = '20553510661-01-F001-1'; const sig = new SignedXml() sig.signingKey = certificate.key sig.keyInfoProvider = new MyKeyInfo(certificate) sig.canonicalizationAlgorithm = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" sig.addReference("//*[local-name(.)=\'ExtensionContent\']", ["http://www.w3.org/2000/09/xmldsig#enveloped-signature"]) sig.computeSignature(xmlinvoice, { location: { reference: "//*[local-name(.)='ExtensionContent']", action: "prepend" }, prefix: 'ds', attrs: { Id: 'SignatureSP' } }) fs.writeFileSync("signed.xml", sig.getSignedXml()) });
dfloresgonz commented 5 years ago

@acporras Prueba esto para hacer tu firmado: Lss funciones crearPEM_from_PFX y crearXML son funciones útiles que creé, si los necesitas me avisas, pero creo que te servirá más saber cómo crear el objeto new SignedXml()


localName = 'Invoice';
pin_certif = 'clave de tu certificado';
ruta_certif = 'ruta donde esta tu certificado';
rutaXML = 'ruta donde esta tu xml';

    function signXML(rutaXML, ruta_certif, pin_certif, localName) {
    return new Promise( async (resolve, reject) => {
        try {
            let SignedXml = require('xml-crypto').SignedXml;
            let DOMParser = require('xmldom').DOMParser;
            ///////////////////////////////
            let xml = fs.readFileSync(rutaXML, 'utf8');
            ///
            let json_pem = await crearPEM_from_PFX(ruta_certif, pin_certif);
            ///
            let transf = ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'];
            let sig = new SignedXml()
            sig.addReference(`//*[local-name(.)='${localName}']`, transf, '', '', '', '', true)
            sig.signingKey =  new Buffer(json_pem.value.key);
            sig.keyInfoProvider = KeyInfoProvider(json_pem.value);
            sig.canonicalizationAlgorithm = 'http://www.w3.org/2001/10/xml-exc-c14n#';
            sig.signatureAlgorithm        = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
            sig.computeSignature(xml, { location: { reference: `//*[local-name(.)='ExtensionContent']`}, prefix: 'ds', attrs: {Id: 'SignatureSP'} });
            const __signedXML = sig.getSignedXml();
            await crearXML(rutaXML,  __signedXML);
            ///////////////////////////////
            let parser = new DOMParser();
            let doc = parser.parseFromString(__signedXML, 'text/xml');
            let hash_cpe = doc.getElementsByTagName('ds:DigestValue')[0].firstChild.data;

            return resolve({ msj : 'El xml ha sido firmado', hash_cpe : hash_cpe, __signedXML : __signedXML });
        } catch(err) {
            return reject({ msj : 'Hubo un error al firmar el XML', stack : err });
        }
    });
}
acporras commented 5 years ago

hola @dfloresgonz gracias por tu respuesta, reutilice la función que me has brindado y a eso después de la siguiente linea:

let hash_cpe = doc.getElementsByTagName('ds:DigestValue')[0].firstChild.data;

Añadí el siguiente código solo para validar mi firma:

var Signature = doc.getElementsByTagName('ds:Signature')[0] sig.loadSignature(xmlserializer.serializeToString(Signature)); var res = sig.checkSignature(__signedXML); if (!res) { console.error(sig.validationErrors); } else { console.log('success'); }

por lo que obtengo el siguiente mensaje:

invalid signature: for uri calculated digest is "primer hash" but the xml to validate supplies digest "segundo hash diferente" es decir que mi firma aun sigue estando mal calculada, tu función me ha ayudado a darme cuenta de que probablemente estoy realizando mal la obtención del proveedor esta es mi función:

`function MyKeyInfo(pem) { this.getKeyInfo = function (key, prefix) { const certLines = pem.cert.split('\n'); let dat = certLines.filter((e, i) => i && e && e.indexOf('-----') !== 0). join('');

    prefix = prefix || ''
    prefix = prefix ? prefix + ':' : prefix
    return `<${prefix}X509Data><${prefix}X509Certificate>${dat}</${prefix}X509Certificate></${prefix}X509Data>`
}
this.getCert = function () {
    //you can use the keyInfo parameter to extract the key in any way you want
    const certLines = pem.cert.split('\n');
    return certLines.filter((e, i) => i && e && e.indexOf('-----') !== 0).
        join('');
}
this.getKey = function (keyinfo) {
    return pem.key
}

}` el cual instancio de la siguiente forma:

sig.keyInfoProvider = new MyKeyInfo(cert);

si pudieras apoyarme mostrándome tu función para poder compararla con la mía te lo agradecería mucho.

dfloresgonz commented 5 years ago

Ok usa este KeyInfoProvider, puedes modificarlo para que tu prefix este dinamico en mi caso lo uso estatico.

function KeyInfoProvider(pem) {
    return {
        getKey() {
            const cert = this.getCert();
            return `<ds:X509Data><ds:X509Certificate>${cert}</ds:X509Certificate></ds:X509Data>`;
        },
        getKeyInfo() {
              const cert = this.getCert();
              return `<ds:X509Data><ds:X509Certificate>${cert}</ds:X509Certificate></ds:X509Data>`;
        },
        getCert() {
            try {
                const certLines = pem.cert.split('\n');
                return certLines.filter((e, i) => i && e && e.indexOf('-----') !== 0).join('');
            } catch (err) {
                throw Error(err);
            }
        }
    };
}
LuisEdgardo commented 4 years ago

Hola amigos, su apoyo por favor: Al firmar una factura xml tengo el siguiente mensaje de error de validación:

SignatureValue SÍ es válido La forma canónica del nodo SignedInfo es </ds:CanonicalizationMethod></ds:SignatureMethod></ds:Transform></ds:Transforms></ds:DigestMethod>Gzfy28Si8glaZAfqCLNaxA/3q+k=</ds:DigestValue></ds:Reference></ds:SignedInfo> La digestión SHA-1 firmada con la que se calculó SignatureValue es pYt19m5bPO+6z+HvaDdcgiMp0oc= La digestión SHA-1 calculada de la forma canonizada de SignedInfo es pYt19m5bPO+6z+HvaDdcgiMp0oc= Reference [0] NO es válida Reference [0] DigestValue contiene Gzfy28Si8glaZAfqCLNaxA/3q+k= Reference [0] DigestValue calculado es cgQ6ekUIdMtqIyYRtjZrlyeUwX8=

Al enviarlo a la SUNAT me indica que el documento ha sido alterado

Este es mi código donde realizo la firma del xml: ` var sig = new SignedXml() const localName = 'Invoice'; const cpath = "//[name()='ext:UBLExtensions']/[name()='ext:UBLExtension']/[name()='ext:ExtensionContent']"; const transf = ["http://www.w3.org/2000/09/xmldsig#enveloped-signature"];

sig.addReference(`//*[local-name(.)='${localName}']`, transf, '', '', '', '', true)
sig.signingKey = fs.readFileSync(pathfilepem)
sig.keyInfoProvider = new MyKeyInfo()
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#" 
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" 

sig.computeSignature(xml, { 
    location:{ 
        reference: "//*[local-name(.)='ExtensionContent']"
    }, 
    prefix: 'ds', 
    attrs: {Id: 'SignatureSP'} 
});
fs.writeFileSync(`${pathfilexml}`, sig.getSignedXml())`

Y este es el código de mi función MyKeyInfo()

`function MyKeyInfo() { this.getKeyInfo = function(key, prefix) { var keyInfoXml, certObj, certBodyInB64;

    prefix = prefix || '';
    prefix = prefix ? prefix + ':' : prefix;

    certBodyInB64 = forge.util.encode64(forge.pem.decode(certificatePEM)[0].body);
    certObj = pki.certificateFromPem(certificatePEM);

    keyInfoXml = '<' + prefix + 'X509Data>';

    keyInfoXml += '<' + prefix + 'X509SubjectName>';
    keyInfoXml += getSubjectName(certObj);
    keyInfoXml += '</' + prefix + 'X509SubjectName>';

    keyInfoXml += '<' + prefix + 'X509Certificate>';
    keyInfoXml += certBodyInB64;
    keyInfoXml += '</' + prefix + 'X509Certificate>';

    keyInfoXml += '</' + prefix + 'X509Data>';

    return keyInfoXml;
  }

}`

`function getSubjectName(certObj) { var subjectFields, fields = ['CN', 'OU', 'O', 'L', 'ST', 'C'];

  if (certObj.subject) {
    subjectFields = fields.reduce(function(subjects, fieldName) {
      var certAttr = certObj.subject.getField(fieldName);

      if (certAttr) {
        subjects.push(fieldName + '=' + certAttr.value);
      }

      return subjects;
    }, []);
  }
  return Array.isArray(subjectFields) ? subjectFields.join(',') : '';
}`

Desde ya gracias por tu valioso apoyo

erwn2793 commented 3 years ago

@tonitim13 @dfloresgonz compatriotas estoy atorado a ver si a uds les ha pasado firmo mi xml y cuando lo envío a la SUNAT me responde esto:

<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
  <soap-env:Header/>
  <soap-env:Body>
      <soap-env:Fault>
          <faultcode>soap-env:Client.2335</faultcode>
          <faultstring>El documento electr&#243;nico ingresado ha sido alterado - Detalle: Incorrect reference digest value</faultstring>
      </soap-env:Fault>
  </soap-env:Body>
</soap-env:Envelope>

en mi xml firmado hay algunas cosas que son diferentes a lo que deberían, por ejemplo en tag

<ds:Reference URI="#_0">

debería ser <ds:Reference URI="">

Hay otras diferencias (comparo con un comprobante que sí pasa la validación) como el ds:X509Certificate que está como que separado en partes y creo que debería ser un string. También está el <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SignatureSP"> que debería tener solo Id y <ext:ExtensionContent Id="_0"> que NO debería tener Id https://i.imgur.com/aDAZz9i.png

EDIT:---------------------- arreglé lo del <ds:Reference URI=""> 😃 lo demás sigue igual y sigo con el mismo error 😢

Tengo el mismo problema, @kamilml como lo solucionaste?

PauloViniciusBaleeiro commented 3 years ago

@erwn2793 Hi! How did you fix <ds:Reference URI="#_0">?

erwn2793 commented 3 years ago

@erwn2793 Hi! How did you fix <ds:Reference URI="#_0">?

Hi! consider this configuration: sig.addReference( "//*[local-name(.)='ExtensionContent']", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'], 'http://www.w3.org/2000/09/xmldsig#sha1', '', '', '', true );

The last value is that defines that part.

PauloViniciusBaleeiro commented 3 years ago

@erwn2793 muchas gracias!

erwn2793 commented 3 years ago

@acporras Prueba esto para hacer tu firmado: Lss funciones crearPEM_from_PFX y crearXML son funciones útiles que creé, si los necesitas me avisas, pero creo que te servirá más saber cómo crear el objeto new SignedXml()

localName = 'Invoice';
pin_certif = 'clave de tu certificado';
ruta_certif = 'ruta donde esta tu certificado';
rutaXML = 'ruta donde esta tu xml';

    function signXML(rutaXML, ruta_certif, pin_certif, localName) {
  return new Promise( async (resolve, reject) => {
      try {
          let SignedXml = require('xml-crypto').SignedXml;
          let DOMParser = require('xmldom').DOMParser;
          ///////////////////////////////
          let xml = fs.readFileSync(rutaXML, 'utf8');
          ///
          let json_pem = await crearPEM_from_PFX(ruta_certif, pin_certif);
          ///
          let transf = ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'];
          let sig = new SignedXml()
          sig.addReference(`//*[local-name(.)='${localName}']`, transf, '', '', '', '', true)
          sig.signingKey =  new Buffer(json_pem.value.key);
          sig.keyInfoProvider = KeyInfoProvider(json_pem.value);
          sig.canonicalizationAlgorithm = 'http://www.w3.org/2001/10/xml-exc-c14n#';
          sig.signatureAlgorithm        = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
          sig.computeSignature(xml, { location: { reference: `//*[local-name(.)='ExtensionContent']`}, prefix: 'ds', attrs: {Id: 'SignatureSP'} });
          const __signedXML = sig.getSignedXml();
          await crearXML(rutaXML,  __signedXML);
          ///////////////////////////////
          let parser = new DOMParser();
          let doc = parser.parseFromString(__signedXML, 'text/xml');
          let hash_cpe = doc.getElementsByTagName('ds:DigestValue')[0].firstChild.data;

          return resolve({ msj : 'El xml ha sido firmado', hash_cpe : hash_cpe, __signedXML : __signedXML });
      } catch(err) {
          return reject({ msj : 'Hubo un error al firmar el XML', stack : err });
      }
  });
}

@dfloresgonz Como escribes el xml?, ya logré realizar la firma y se valida de forma correcta pero cuando envío el xml a sunat me devuelve que el documento fue alterado, sin embargo si pinto el xml en un log y lo escribo manualmente como xml sunat lo acepta

Joes-BM commented 3 years ago

@acporras si pudieras apoyarme con las funciones que creaste para probar el codigo te lo agradeceria bastante, joe.bm@msn.com

dfloresgonz commented 3 years ago

Hola gente,

Por si lo necesitan:

function crearXML(rutaFile, xmlData) {
    return new Promise( (resolve, reject) => {
        try {
            fs.writeFileSync(rutaFile, xmlData, 'utf8');
            return resolve({ msj : 'Se creo el xml' });
        } catch(err) {
            return reject({ err : err, msj : 'Hubo un error al crear el XML' });
        }
    });
}

Ojo aqui con la ruta del openssl lo puse asi porque lo tengo subido en AWS

function crearPEM_from_PFX(ruta_certif, pin_certif) {
    return new Promise( (resolve, reject) => {
        try {
            const pem = require('pem');
            pem.config({
                pathOpenSSL: path.resolve('/opt/nodejs/openssl/bin/openssl')
            });
            const pfx = fs.readFileSync(ruta_certif);
            pem.readPkcs12(pfx, { p12Password : pin_certif }, async (err, new_pem) => {
                if(err) {
                    return reject({ msj : 'Hubo un error en el pem.readPkcs12', stack : err });
                }
                return resolve({ value : new_pem });
            });
        } catch(err) {
            return reject({ err : err, msj : 'Hubo un error al crear el PEM' });
        }
    });
}
erwn2793 commented 3 years ago

Hola gente,

Por si lo necesitan:

function crearXML(rutaFile, xmlData) {
  return new Promise( (resolve, reject) => {
      try {
          fs.writeFileSync(rutaFile, xmlData, 'utf8');
          return resolve({ msj : 'Se creo el xml' });
      } catch(err) {
          return reject({ err : err, msj : 'Hubo un error al crear el XML' });
      }
  });
}

Ojo aqui con la ruta del openssl lo puse asi porque lo tengo subido en AWS

function crearPEM_from_PFX(ruta_certif, pin_certif) {
  return new Promise( (resolve, reject) => {
      try {
          const pem = require('pem');
          pem.config({
              pathOpenSSL: path.resolve('/opt/nodejs/openssl/bin/openssl')
          });
          const pfx = fs.readFileSync(ruta_certif);
          pem.readPkcs12(pfx, { p12Password : pin_certif }, async (err, new_pem) => {
              if(err) {
                  return reject({ msj : 'Hubo un error en el pem.readPkcs12', stack : err });
              }
              return resolve({ value : new_pem });
          });
      } catch(err) {
          return reject({ err : err, msj : 'Hubo un error al crear el PEM' });
      }
  });
}

Gracias!!! funciono para mi.

ejenry commented 3 years ago

@dfloresgonz tmb estoy intentado implementar FE en node, pero mis métodos no funcionan, me sale el error de q el documento es alterado, probé con tus funciones mencionadas y sigue igual, el error es el siguiente `SignatureValue SÍ es válido La forma canónica del nodo SignedInfo es

a7ue3wnVG/t3YjV+yPk1cdZFnXM= La digestión SHA-1 firmada con la que se calculó SignatureValue es SQ5PKJIbewzQSi/nyi7Ha8Bjg+U= La digestión SHA-1 calculada de la forma canonizada de SignedInfo es SQ5PKJIbewzQSi/nyi7Ha8Bjg+U= Reference [0] NO es válida Reference [0] DigestValue contiene a7ue3wnVG/t3YjV+yPk1cdZFnXM= Reference [0] DigestValue calculado es /vS0l8B6dU8aK1LAo2y1zQLw9jU=` Aparentemente por el digest value, pero no se como solucionarlo, @erwn2793 como solucionaste el error? talvez es por lo del openSSL, ya que estoy haciendo pruebas en Windows, descargué y configuré para Windows, pero nada
iaguedo commented 3 years ago

Buenas, lograron solucionar esto: Signature Id="SignatureSP" xmlns="http://www.w3.org/2000/09/xmldsig#"

eduardowin commented 2 years ago

Hola compatriotas, buenos dias, una consulta lograon solucionar el mensaje de: "El documento electrónico ingresado ha sido alterado - Detalle: Incorrect reference digest value", estoy buscando alguna opcion y no logro obtenerla.