node-saml / xml-crypto

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

enveloped signature transform without c14n-20010315 workaround #210

Open Flyingpeanut opened 4 years ago

Flyingpeanut commented 4 years ago

Hi, First of all I would like to apologize if my issue is redundant, I am not very experienced in xml signatures. I would like to sign my document with only enveloped-signature as transform I have based my code on #93 solution I use this function to sign

const forge = require('node-forge'),
    pki = forge.pki,
    select = require('xml-crypto').xpath
  , dom = require('xmldom').DOMParser
  , SignedXml = require('xml-crypto').SignedXml
  , FileKeyInfo = require('xml-crypto').FileKeyInfo  
  , fs = require('fs');

function signXML(){
    let sig = new SignedXml()
  sig.addReference("//*[local-name(.)='elmo']",[
      'http://www.w3.org/2000/09/xmldsig#enveloped-signature',]
      //'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
     ,'http://www.w3.org/2001/04/xmlenc#sha256',"","","",true)
  sig.signingKey = RSA_key
  sig.keyInfoProvider = new KeyInfoProvider(RSA_cert)
  sig.canonicalizationAlgorithm = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
  sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
  sig.computeSignature(xml )
  fs.writeFileSync("signed.xml", sig.getSignedXml())
}
// and this to validate the signed xml

function testValidate(){
  var xml = fs.readFileSync("signed.xml").toString()
  var doc = new dom().parseFromString(xml)    
  var signature = select(doc, "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")
  var sig = new SignedXml()
  sig.keyInfoProvider = new KeyInfoProvider(fs.readFileSync("client_public.pem"))
  sig.loadSignature(signature[0].toString())
  var res = sig.checkSignature(xml)
  if (!res) console.log(sig.validationErrors)
    console.log(res);
  return res
}

It shouldn't be relevant I am have taken this from another issue #47 to create the X509Data

  function KeyInfoProvider(certificatePEM) {
    if (!this instanceof KeyInfoProvider) {
      return new KeyInfoProvider();
    }

    if (Buffer.isBuffer(certificatePEM)) {
      certificatePEM = certificatePEM.toString('ascii');
    }

    if (certificatePEM == null || typeof certificatePEM !== 'string') {
      throw new Error('certificatePEM must be a valid certificate in PEM format');
    }

    this._certificatePEM = certificatePEM;

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

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

      certBodyInB64 = forge.util.encode64(forge.pem.decode(this._certificatePEM)[0].body);
      certObj = pki.certificateFromPem(this._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;
    };

    this.getKey = function() {
      return this._certificatePEM;
    };
  }

  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(',') : '';
    }

, but when I run with REC-xml-c14n-20010315 transform everything is ok but when I remove it from the transforms I get this error:

'invalid signature: for uri calculated digest is 4iuVYZhLYEepzst9YiHiGQmV9mk= but the xml to validate supplies digest 5g4Z1MB1xEH45DlQwOmsxgM1GpA='

It it possible to make signature with only enveloped signature as transform?

HariAmbadi commented 4 years ago

I am also facing this exact issue. It it possible to make sign and verify with only enveloped signature as transform algorithm?

Any help on this will be highly appreciated

clucher91 commented 2 years ago

Any solutions ? I Have the same problem

iaguedo commented 1 year ago

alguien lo logro soluionar?

cjbarth commented 1 year ago

Off hand, I don't know if what you're asking for is possible, but if you created a PR with a test that fails that clearly shows what you're after, it will speed up the process of getting a fix and will ensure that the feature/fix that you're after stays working. @Flyingpeanut , @HariAmbadi , @clucher91 or @iaguedo would any of you be willing to do that?