Skip to content

Wrong Digest Value generated. Actual XML and Expected XML is not matching. Working from last three nights. #212

Closed

Description

@niladrinic

Dear All,
I have used this library to generate a signature which is done at root level. The signed xml is not matching as per the expected xml. The digested value and signature value is not matching with real real value. Can't figure this out working from last three night and almost gone mad. please help me out.

var builder = require('xmlbuilder');
var SignedXml = require('xml-crypto').SignedXml;
var fs = require("fs");

module.exports.SXML = function() {
    //Created the request XML as per the required format
    var xml = builder.create('Esign').att('AuthMode', '1').att('aspId', 'TNIC-001').att('kycId', '')
        .att('ekycIdType', 'A').att('responseSigType', "pkcs7")
        .att('responseUrl', 'https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1')
        .att('sc', 'Y').att('ts', '2020-05-19T11:28:01').att('txn', '999-ESIGN-DIVISION-2020-05-19T11:28:01')
        .att('ver', '2.1');
    //xml.ele("Docs").ele("InputHash",{'docInfo':'hello', 'hashAlgorithm':'SHA256', 'id':'1'},'5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e');
    xml.ele("Docs").ele("InputHash", {
        'docInfo': 'hello',
        'hashAlgorithm': 'SHA256',
        'id': '1'
    }, '5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e');

    // XML doc is ready for signing. Converted to String 
    var xmldoc = xml.toString({
        pretty: true
    });

    var sig = new SignedXml();
    //sig.addReference("/*",['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],'http://www.w3.org/2001/04/xmlenc#sha256','','','',true);
    sig.addReference("/*", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'], 'http://www.w3.org/2000/09/xmldsig#sha1', '', '', '', true);


    sig.signingKey = fs.readFileSync("nicesign.pem");
    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(xmldoc.toString());

    return sig.getSignedXml();
}

Output XML is:

<Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
  <Docs>
    <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
  </Docs>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>4IoV5vTOEUL9jI4p5N2Z+oq6rgY=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>qQ4DZk+OZNMsalFk2J9ke9QEyv0FwqpBbY2k5s22JivHPuC0lbhxW0xAH7XOkTB4s6kJGL3sf1+Q19V8BL1uX62AgJeWukkQ9qWf72KmIVOT6DUqKDst2rFIZRLUSSNwBqfspzX2aQbHriImLll0LOAkha5bFAZSLlzClVDR0ULGkMEfVfe+e6p84b7zY5HRrH2nBXF1+37C/TUA7pLnUGqP9WILRyh4z+2qguhZTV5oqNWDCFJ1JfwxYJqr+1YVqhIc4AK6v0c3MmPRElH97t98D/R+NVqy3GpOCX9+LldqLJJbCoVnYWMOAb2Au1Cf1K0gg5GJpIjtEGIJT80dXA==</SignatureValue>
  </Signature>
</Esign>

Expected Output is: (Difference in digest value and even if the algorithm mentioned in this same as well as content of the XML)

<Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
  <Docs>
    <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
  </Docs>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>4IoV5vTOEUL9jI4p5N2Z+oq6rgY=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>qQ4DZk+OZNMsalFk2J9ke9QEyv0FwqpBbY2k5s22JivHPuC0lbhxW0xAH7XOkTB4s6kJGL3sf1+Q19V8BL1uX62AgJeWukkQ9qWf72KmIVOT6DUqKDst2rFIZRLUSSNwBqfspzX2aQbHriImLll0LOAkha5bFAZSLlzClVDR0ULGkMEfVfe+e6p84b7zY5HRrH2nBXF1+37C/TUA7pLnUGqP9WILRyh4z+2qguhZTV5oqNWDCFJ1JfwxYJqr+1YVqhIc4AK6v0c3MmPRElH97t98D/R+NVqy3GpOCX9+LldqLJJbCoVnYWMOAb2Au1Cf1K0gg5GJpIjtEGIJT80dXA==</SignatureValue>
  </Signature>
</Esign>

Activity

  1. djaqua commented on May 8, 2023

    @djaqua
    Contributor

    @niladrinic did you ever figure this out or do you still need help with it?

  2. cjbarth commented on May 29, 2023

    @cjbarth
    Contributor

    @niladrinic , I've pretty printed your code and used properly labeled fences to make it much easier to read. After pretty printing the XML, it appears that both are the same. If more help is needed, more information is needed. Please reply with more information to reopen this.

  3. CarlaMck77 commented on Aug 13, 2023

    @CarlaMck77

    I have a mismatched DigestValue and SignatureValue as well. I have no idea how to fix it. This is new to me.

    Have you figured out what was causing this issue?

  4. cfficaurzua commented on Feb 15, 2024

    @cfficaurzua

    i have the same problem
    I checked byte by byte
    the digest value is indeed wrong
    other libraries with same configuration gets another value
    I also check with this tool https://tools.chilkat.io/xmlDsigVerify.cshtml

  5. cjbarth commented on Feb 15, 2024

    @cjbarth
    Contributor

    I am sorry that you're having issues. We certainly want to fix them, however, we don't have enough information to help. The original post lists the expected output as the exact same as the produced output, so we've got nothing to go on there. Please provide more information, sample code, received vs. expected, etc., otherwise there is nothing that anyone can do to help.

  6. srd90 commented on Feb 16, 2024

    @srd90

    Issue reporters didn't share anything to work with so lets try at least something.

    At the time when issue was raised (based on timestamp) xml-crypto version was 1.5.3 and xmlbuilder is/was 15.1.1.

    This gives us about following package.json

    {
      "name": "foo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "xml-crypto": "1.5.3",
        "xmlbuilder": "15.1.1"
      }
    }

    BUT lets start by asking second opinion about Digest value from xmlsec1 tool:

    #!/bin/bash
    
    FOODIR=/tmp/xml-crypto-212
    KEY=$FOODIR/nicesign.pem
    CERT=$FOODIR/nicesign_cert.pem
    KEYSTORE=$FOODIR/keystore.p12
    TO_BE_SIGNED=$FOODIR/to_be_signed.xml
    SIGNED=$FOODIR/signed.xml
    
    mkdir -p $FOODIR
    
    # https://github.com/node-saml/xml-crypto/issues/212
    # didn't provide used signing key so lets use this as "nicesign.pem":
    wget -O $KEY https://raw.githubusercontent.com/node-saml/xml-crypto/21201723d2ca9bc11288f62cf72552b7d659b000/test/static/client.pem
    
    wget -O $CERT https://raw.githubusercontent.com/node-saml/xml-crypto/21201723d2ca9bc11288f62cf72552b7d659b000/test/static/client_public.pem
    
    openssl \
      pkcs12 \
      -nodes \
      -export \
      -out $KEYSTORE \
      -inkey $KEY \
      -in $CERT \
      -passout pass:password
    
    # content of XML document produced by https://github.com/node-saml/xml-crypto/issues/212
    # augmented with "signing template" for xmlsec1. Content of signing template was deducted from
    # output of issue report's code snippets output.
    cat <<EOF >$TO_BE_SIGNED
    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue/></Reference></SignedInfo><SignatureValue/></Signature></Esign>
    EOF
    
    xmlsec1 \
      --sign \
      --print-debug \
      --id-attr:ID Esign \
      --output $SIGNED \
      --pkcs12 $KEYSTORE \
      --pwd password \
      $TO_BE_SIGNED
    
    cat $SIGNED

    Script output is:

    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue></Reference></SignedInfo><SignatureValue>jfWA3qHH0fWFbZCqUHKlu1oc/vcfVdOV8yZMlqNVkCgwpP7m2HjDLt2j0NZJzFLd
    BBLMXxc/Qb96MUra5g8bfOsIHjDW1Qh+GLovd+PO79TpZ4TPNMxJNy/bT82bXpjn
    T1QCH3hNT82NQ0gZ1kgwkVmSJ/hNmQXgD4Sp+5YiBT4=</SignatureValue></Signature></Esign>

    and DigestValue is:

    <DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue>

    if produced signed XML is pasted to https://tools.chilkat.io/xmlDsigVerify.cshtml it reports

    Reference 1 digest is valid.
    

    Pretty printed version of output signed xml for better readability

    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <Reference URI="">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>jfWA3qHH0fWFbZCqUHKlu1oc/vcfVdOV8yZMlqNVkCgwpP7m2HjDLt2j0NZJzFLd
    BBLMXxc/Qb96MUra5g8bfOsIHjDW1Qh+GLovd+PO79TpZ4TPNMxJNy/bT82bXpjn
    T1QCH3hNT82NQ0gZ1kgwkVmSJ/hNmQXgD4Sp+5YiBT4=</SignatureValue>
      </Signature>
    </Esign>

    Now lets try with code snippet from issue report

    /*
    Related to https://github.com/node-saml/xml-crypto/issues/212
    
    Issue doesn't give any hint about any version thus reasoned
    from timestamps that xml-crypto version might have been 1.5.3
    and xmlbuilder might have been 15.1.1
    
    Dunno about nodejs version. This investigation is done with
    npm 6.14.18
    node v14.21.3
    
    and with following package.json
    {
      "name": "foo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "xml-crypto": "1.5.3",
        "xmlbuilder": "15.1.1"
      }
    }
    
    Furthermore example code at issue https://github.com/node-saml/xml-crypto/issues/212
    didn't have content of "nicesign.pem" thus used this key as "nicesign.pem"
    https://raw.githubusercontent.com/node-saml/xml-crypto/21201723d2ca9bc11288f62cf72552b7d659b000/test/static/client.pem
    */
    var nicesign_pem = `
    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL4vpoH3H3byehjj
    7RAGxefGRATiq4mXtzc9Q91W7uT0DTaFEbjzVch9aGsNjmLs4QHsoZbuoUmi0st4
    x5z9SQpTAKC/dW8muzacT3E7dJJYh03MAO6RiH4LG34VRTq1SQN6qDt2rCK85eG4
    5NHI4jceptZNu6Zot1zyO5/PYuFpAgMBAAECgYAhspeyF3M/xB7WIixy1oBiXMLY
    isESFAumgfhwU2LotkVRD6rgNl1QtMe3kCNWa9pCWQcYkxeI0IzA+JmFu2shVvoR
    oL7eV4VCe1Af33z24E46+cY5grxNhHt/LyCnZKcitvCcrzXExUc5n6KngX0mMKgk
    W7skZDwsnKzhyUV8wQJBAN2bQMeASQVOqdfqBdFgC/NPnKY2cuDi6h659QN1l+kg
    X3ywdZ7KKftJo1G9l45SN9YpkyEd9zEO6PMFaufJvZUCQQDbtAWxk0i8BT3UTNWC
    T/9bUQROPcGZagwwnRFByX7gpmfkf1ImIvbWVXSpX68/IjbjSkTw1nj/Yj1NwFZ0
    nxeFAkEAzPhRpXVBlPgaXkvlz7AfvY+wW4hXHyyi0YK8XdPBi25XA5SPZiylQfjt
    Z6iN6qSfYqYXoPT/c0/QJR+orvVJNQJBANhRPNXljVTK2GDCseoXd/ZiI5ohxg+W
    UaA/1fDvQsRQM7TQA4NXI7BO/YmSk4rW1jIeOxjiIspY4MFAIh+7UL0CQFL6zTg6
    wfeMlEZzvgqwCGoLuvTnqtvyg45z7pfcrg2cHdgCXIy9kErcjwGiu6BOevEA1qTW
    Rk+bv0tknWvcz/s=
    -----END PRIVATE KEY-----
    `
    
    var builder = require('xmlbuilder');
    var SignedXml = require('xml-crypto').SignedXml;
    var fs = require("fs");
    
    function SXML() { //module.exports.SXML = function() {
    
        //Created the request XML as per the required format
        var xml = builder.create('Esign').att('AuthMode', '1').att('aspId', 'TNIC-001').att('kycId', '')
            .att('ekycIdType', 'A').att('responseSigType', "pkcs7")
            .att('responseUrl', 'https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1')
            .att('sc', 'Y').att('ts', '2020-05-19T11:28:01').att('txn', '999-ESIGN-DIVISION-2020-05-19T11:28:01')
            .att('ver', '2.1');
        //xml.ele("Docs").ele("InputHash",{'docInfo':'hello', 'hashAlgorithm':'SHA256', 'id':'1'},'5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e');
        xml.ele("Docs").ele("InputHash", {
            'docInfo': 'hello',
            'hashAlgorithm': 'SHA256',
            'id': '1'
        }, '5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e');
    
        // XML doc is ready for signing. Converted to String 
        var xmldoc = xml.toString({
            pretty: true
        });
    
        var sig = new SignedXml();
        //sig.addReference("/*",['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],'http://www.w3.org/2001/04/xmlenc#sha256','','','',true);
        sig.addReference("/*", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'], 'http://www.w3.org/2000/09/xmldsig#sha1', '', '', '', true);
    
    
        sig.signingKey = nicesign_pem; // fs.readFileSync("nicesign.pem");
        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(xmldoc.toString());
    
        return sig.getSignedXml();
    }
    
    console.log(SXML());

    Output signed XML is:

    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>4IoV5vTOEUL9jI4p5N2Z+oq6rgY=</DigestValue></Reference></SignedInfo><SignatureValue>cPynLKSHAvTg90BueCU0PsHxoLqaF7U62nH19a5TWH2Wq1ohShKTF6adElSgnbyYllTgOiUQwAGb+T8gblxnOtMTOZdq3ktc1AbncrZ9PC75PVvlCiVP4Du/GRDgS+E0/PPb0Iuy3zzBGwMjE5qo5rCcjgfeGtoLgCsFw2HXaV8=</SignatureValue></Signature></Esign>

    and DigestValue is:

    <DigestValue>4IoV5vTOEUL9jI4p5N2Z+oq6rgY=</DigestValue>

    if produced signed XML is pasted to https://tools.chilkat.io/xmlDsigVerify.cshtml it reports

    Reference 1 digest is invalid because the computed digest differs from the digest in the XML.
    

    Pretty printed version of output signed xml for better readability

    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <Reference URI="">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>4IoV5vTOEUL9jI4p5N2Z+oq6rgY=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>cPynLKSHAvTg90BueCU0PsHxoLqaF7U62nH19a5TWH2Wq1ohShKTF6adElSgnbyYllTgOiUQwAGb+T8gblxnOtMTOZdq3ktc1AbncrZ9PC75PVvlCiVP4Du/GRDgS+E0/PPb0Iuy3zzBGwMjE5qo5rCcjgfeGtoLgCsFw2HXaV8=</SignatureValue>
      </Signature>
    </Esign>

    FWIW,

    1. if xml-crypto 3.1.0 is used result is same.
    2. no point to try with 4.x and 5.x because those should be marked vulnerable and no-one should use those
    3. I did not have time to modify issue code snippet to work with xml-crypto 6.0.0

    quick grepping around xml-crypto codebase about used algorithms it turned out that http://www.w3.org/TR/2001/REC-xml-c14n-20010315 is not explicitly tested.

    Based on aforementioned observation searching issues which have string 20010315: https://github.com/node-saml/xml-crypto/issues?q=is%3Aissue+is%3Aopen+20010315

    returned among other things #210 (tl;dr; with just enveloped-signature at transformatons array digest values mismatch but with enveloped-signature followed by REC-xml-c14n-20010315 digest values matched ).

    Lets try to add REC-xml-c14n-20010315 to the transformations list:

    /*
    Related to https://github.com/node-saml/xml-crypto/issues/212
    
    npm 6.14.18
    node v14.21.3
    
    {
      "name": "foo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "xml-crypto": "1.5.3",
        "xmlbuilder": "15.1.1"
      }
    }
    */
    var nicesign_pem = `
    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL4vpoH3H3byehjj
    7RAGxefGRATiq4mXtzc9Q91W7uT0DTaFEbjzVch9aGsNjmLs4QHsoZbuoUmi0st4
    x5z9SQpTAKC/dW8muzacT3E7dJJYh03MAO6RiH4LG34VRTq1SQN6qDt2rCK85eG4
    5NHI4jceptZNu6Zot1zyO5/PYuFpAgMBAAECgYAhspeyF3M/xB7WIixy1oBiXMLY
    isESFAumgfhwU2LotkVRD6rgNl1QtMe3kCNWa9pCWQcYkxeI0IzA+JmFu2shVvoR
    oL7eV4VCe1Af33z24E46+cY5grxNhHt/LyCnZKcitvCcrzXExUc5n6KngX0mMKgk
    W7skZDwsnKzhyUV8wQJBAN2bQMeASQVOqdfqBdFgC/NPnKY2cuDi6h659QN1l+kg
    X3ywdZ7KKftJo1G9l45SN9YpkyEd9zEO6PMFaufJvZUCQQDbtAWxk0i8BT3UTNWC
    T/9bUQROPcGZagwwnRFByX7gpmfkf1ImIvbWVXSpX68/IjbjSkTw1nj/Yj1NwFZ0
    nxeFAkEAzPhRpXVBlPgaXkvlz7AfvY+wW4hXHyyi0YK8XdPBi25XA5SPZiylQfjt
    Z6iN6qSfYqYXoPT/c0/QJR+orvVJNQJBANhRPNXljVTK2GDCseoXd/ZiI5ohxg+W
    UaA/1fDvQsRQM7TQA4NXI7BO/YmSk4rW1jIeOxjiIspY4MFAIh+7UL0CQFL6zTg6
    wfeMlEZzvgqwCGoLuvTnqtvyg45z7pfcrg2cHdgCXIy9kErcjwGiu6BOevEA1qTW
    Rk+bv0tknWvcz/s=
    -----END PRIVATE KEY-----
    `
    
    var builder = require('xmlbuilder');
    var SignedXml = require('xml-crypto').SignedXml;
    var fs = require("fs");
    
    function SXML() { //module.exports.SXML = function() {
    
        //Created the request XML as per the required format
        var xml = builder.create('Esign').att('AuthMode', '1').att('aspId', 'TNIC-001').att('kycId', '')
            .att('ekycIdType', 'A').att('responseSigType', "pkcs7")
            .att('responseUrl', 'https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1')
            .att('sc', 'Y').att('ts', '2020-05-19T11:28:01').att('txn', '999-ESIGN-DIVISION-2020-05-19T11:28:01')
            .att('ver', '2.1');
        //xml.ele("Docs").ele("InputHash",{'docInfo':'hello', 'hashAlgorithm':'SHA256', 'id':'1'},'5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e');
        xml.ele("Docs").ele("InputHash", {
            'docInfo': 'hello',
            'hashAlgorithm': 'SHA256',
            'id': '1'
        }, '5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e');
    
        // XML doc is ready for signing. Converted to String 
        var xmldoc = xml.toString({
            pretty: true
        });
    
        var sig = new SignedXml();
        //sig.addReference("/*",['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],'http://www.w3.org/2001/04/xmlenc#sha256','','','',true);
    
    // NOTE: added http://www.w3.org/TR/2001/REC-xml-c14n-20010315 to the transformations list
        sig.addReference("/*", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'], 'http://www.w3.org/2000/09/xmldsig#sha1', '', '', '', true);
    
    
        sig.signingKey = nicesign_pem; // fs.readFileSync("nicesign.pem");
        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(xmldoc.toString());
    
        return sig.getSignedXml();
    }
    
    console.log(SXML());

    Output signed XML is:

    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue></Reference></SignedInfo><SignatureValue>Pq2/YfGPOn6FuCVajV+EL3ZWZmIzXeiQtDVG6QawaEC1Vzp1xjDMkdmL9/o0w8P/bqTCuWBR3Yc8gTBlc9Busdwv3PEuWYggN/WTrP63FXGDDO2VxcejoQMsclIJ+C3BaO1zFRN11XbCt44xSUDtufUCwPE08HzQXFfeeOUl/jw=</SignatureValue></Signature></Esign>

    and DigestValue is:

    <DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue>

    if produced signed XML is pasted to https://tools.chilkat.io/xmlDsigVerify.cshtml it reports

    Reference 1 digest is valid.
    

    Pretty printed version of output signed xml for better readability

    <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <Reference URI="">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
              <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>Pq2/YfGPOn6FuCVajV+EL3ZWZmIzXeiQtDVG6QawaEC1Vzp1xjDMkdmL9/o0w8P/bqTCuWBR3Yc8gTBlc9Busdwv3PEuWYggN/WTrP63FXGDDO2VxcejoQMsclIJ+C3BaO1zFRN11XbCt44xSUDtufUCwPE08HzQXFfeeOUl/jw=</SignatureValue>
      </Signature>
    </Esign>

    So:

    1. "second opinion case" produced digest (without explicitly listing REC-xml-c14n-20010315 transform) which passed XmlDsigVerify's test.
    2. modified issue report code snippet (explicitly adding REC-xml-c14n-20010315 to the transformations list) produced exactly same digest as "second opinion case" and XmlDsigVerify had same opinion about digest value.

    I have no idea whats actually wrong with xml-crypto <= 3.1.0 versions (didn't test with >= 6.x) but now there exists some test material for debugging and comparing with outputs of other tools.

    I don't have any idea who (xml-crypto, xmlsec1 and/or XmlDsigVerify) is interpreting spec correctly.

    edit: added pretty printed versions of signed output xmls for better readability

  7. srd90 commented on Feb 16, 2024

    @srd90

    Testing whether #212 (comment) comments "second opinion case's" signed xml output verifies without errors with xml-crypto 1.5.3 (note: that XML has digestvalue that matches with content based on "third opinion" and that particular XML doesn't have explicitly listed REC-xml-c14n-20010315 transformation at transformations list:

    /*
    Relaed to https://github.com/node-saml/xml-crypto/issues/212
    
    Test signature validation part of https://github.com/node-saml/xml-crypto/tree/v1.5.3
    when transformations list contains only enveloped-signature
    
    npm 6.14.18
    node v14.21.3
    
    {
      "name": "foo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "xml-crypto": "1.5.3",
        "xmlbuilder": "15.1.1"
      }
    }
    */
    var select = require('xml-crypto').xpath
        , dom = require('xmldom').DOMParser
        , SignedXml = require('xml-crypto').SignedXml
        , fs = require('fs')
    
    // output of https://github.com/node-saml/xml-crypto/issues/212#issuecomment-1949310736
    // comments "second opinion case" (of xmlsec1)
    // Notice the absence of second transformation
    var xml = `
      <Esign AuthMode="1" aspId="TNIC-001" kycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="https://nic-esigngateway.nic.in/eSign21/response?rs=localhost:8080/Esign_client/hello1" sc="Y" ts="2020-05-19T11:28:01" txn="999-ESIGN-DIVISION-2020-05-19T11:28:01" ver="2.1">
      <Docs>
        <InputHash docInfo="hello" hashAlgorithm="SHA256" id="1">5df2936623312f38371871bf5226e666c66318329d826bf7db544237096a837e</InputHash>
      </Docs>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>1vWDVKN2jliWtO825GBmO4M3il4=</DigestValue></Reference></SignedInfo><SignatureValue>jfWA3qHH0fWFbZCqUHKlu1oc/vcfVdOV8yZMlqNVkCgwpP7m2HjDLt2j0NZJzFLd
    BBLMXxc/Qb96MUra5g8bfOsIHjDW1Qh+GLovd+PO79TpZ4TPNMxJNy/bT82bXpjn
    T1QCH3hNT82NQ0gZ1kgwkVmSJ/hNmQXgD4Sp+5YiBT4=</SignatureValue></Signature></Esign>
    `
    
    // https://raw.githubusercontent.com/node-saml/xml-crypto/21201723d2ca9bc11288f62cf72552b7d659b000/test/static/client_public.pem
    var cert = `
    -----BEGIN CERTIFICATE-----
    MIIBxDCCAW6gAwIBAgIQxUSXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BAQQFADAW
    MRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ3NTlaFw0zOTEyMzEy
    MzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0Q2xpZW50MIGfMA0GCSqG
    SIb3DQEBAQUAA4GNADCBiQKBgQC+L6aB9x928noY4+0QBsXnxkQE4quJl7c3PUPd
    Vu7k9A02hRG481XIfWhrDY5i7OEB7KGW7qFJotLLeMec/UkKUwCgv3VvJrs2nE9x
    O3SSWIdNzADukYh+Cxt+FUU6tUkDeqg7dqwivOXhuOTRyOI3HqbWTbumaLdc8juf
    z2LhaQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEU
    MBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcN
    AQEEBQADQQAfIbnMPVYkNNfX1tG1F+qfLhHwJdfDUZuPyRPucWF5qkh6sSdWVBY5
    sT/txBnVJGziyO8DPYdu2fPMER8ajJfl
    -----END CERTIFICATE-----
    `
    
    var doc = new dom().parseFromString(xml)    
    
    var signature = select(doc, "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0]
    var sig = new SignedXml()
    sig.keyInfoProvider = {
      getKey: function(keyInfo) {
        return cert;
      }
    }
    sig.loadSignature(signature)
    var res = sig.checkSignature(xml)
    if (!res) {
      console.log(sig.validationErrors)
    } else {
      console.log("No validation errors.")
    }

    output is

    No validation errors.
    

    based on this it seems/feels as if this (from 1.5.3) would not be applied symmetrically (i.e. as if it would be applied to signature validation part only where-as other tools seem to be applying implicitly for digestvalue calculaton also or something like that):

    /**
    * DigestMethods take an octet stream rather than a node set. If the output of the last transform is a node set, we
    * need to canonicalize the node set to an octet stream using non-exclusive canonicalization. If there are no
    * transforms, we need to canonicalize because URI dereferencing for a same-document reference will return a node-set.
    * See:
    * https://www.w3.org/TR/xmldsig-core1/#sec-DigestMethod
    * https://www.w3.org/TR/xmldsig-core1/#sec-ReferenceProcessingModel
    * https://www.w3.org/TR/xmldsig-core1/#sec-Same-Document
    */
    if (transforms.length === 0 || transforms[transforms.length - 1] === "http://www.w3.org/2000/09/xmldsig#enveloped-signature") {
    transforms.push("http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
    }

  8. cjbarth commented on Feb 17, 2024

    @cjbarth
    Contributor

    @srd90 your sample code here gives a lot to go on, and I'm glad you were able to find this. @niladrinic , @CarlaMck77 , @cfficaurzua , if any of you would like to put up a PR to address this, that would be most welcome. I don't know when I'll have time to look into this, especially since this problem isn't affecting anything I'm working on. Even if you just put up a PR with a test that fails, that would be a huge help to getting things rolling.

  9. cjbarth commented on Sep 24, 2026

    @cjbarth
    Contributor

    This was fixed by #581, released in 6.2.0. When enveloped-signature was the only transform, signing hashed xmldom's serialization of the node while verification applied the implicit C14N, so the two disagreed. Both sides now canonicalize a node-set left at the end of the transforms, as the XMLDSig reference processing model requires.

    With 6.3.2, the reproduction in #212 (comment) produces 1vWDVKN2jliWtO825GBmO4M3il4=, the digest xmlsec1 computed, without listing the C14N transform explicitly. 6.1.2 still produced 4IoV5vTOEUL9jI4p5N2Z+oq6rgY=.

    If you still see a digest mismatch on 6.3.2 or later, please comment here with a reproduction and we'll reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions