javascriptxmlbankonlinebanking

EBICS XML Signature in Javascript


it's my first time asking in stackoverflow basically right now I am trying to implement EBICS current progress in on HPB

I already created an XML with this format

<?xml version="1.0" encoding="UTF-8"?>
<ebicsNoPubKeyDigestsRequest xmlns="urn:org:ebics:H004" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:org:ebics:H004 ebics_keymgmt_request_H004.xsd" Version="H004" Revision="1">
    <header authenticate="true">
        <static>
            <HostID>{HostID}</HostID>
            <Nonce>{Nonce}</Nonce>
            <Timestamp>{CurrentTimestamp}</Timestamp>
            <PartnerID>{ID}</PartnerID>
            <UserID>{ID}</UserID>
            <OrderDetails>
                <OrderType>HPB</OrderType>
                <OrderAttribute>DZHNN</OrderAttribute>
            </OrderDetails>
            <SecurityMedium>0000</SecurityMedium>
        </static>
        <mutable/>
    </header>
    <AuthSignature>
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
            <ds:Reference URI="#xpointer(//*[@authenticate='true'])">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <ds:DigestValue>....Digest value here...</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>...Signature value here....</ds:SignatureValue>
    </AuthSignature>
    <body/>
</ebicsNoPubKeyDigestsRequest>

But it always return Signature invalid after check with the bank, they say the DigestValue is not match with the one they generated Here is the code to generate Digest Value

// **************** Import library ****************
const crypto = require('crypto');
const C14n =    require('xml-crypto/lib/c14n-canonicalization').C14nCanonicalization;
const { DOMParser, XMLSerializer } = require('@xmldom/xmldom');
const xpath = require('xpath');

/**
 * To return digest result based on hash algorithm
 * @param {*} data: string that will be hash
 * @param {*} algorithm: algorithm used, default is sha256
 * @returns 
 */
function digestWithHash(data, algorithm = 'sha256') {
  const digestHash = forge.md.sha256.create();

  digestHash.update(data);

  // return digestHash.digest().toHex()
  return crypto.createHash(algorithm)
    .update(data)
    .digest();
}

/**
 * Generate Digest Value
 * @param {*} doc 
 */
function GenerateDigestValue(doc) {
  // **************** get the xml node, where the digested value is supposed to be
  const nodeDigestValue = doc.getElementsByTagName('ds:DigestValue')[0];

  // **************** canonicalize the node that has authenticate='true' attribute
  const contentToDigest = xpath
    .select("//*[@authenticate='true']", doc)
    .map(x => new C14n().process(x))
    .join('');

  // **************** fix the canonicalization
  const fixedContent = contentToDigest
    .replace(/&#xD;/g, '')
    .replace(
      /xmlns="urn:org:ebics:H004"/g,
      'xmlns="urn:org:ebics:H004" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"',
    );

  

  // **************** Write file as type XML
  fs.writeFileSync("./xml/Canonized-HPB-header.xml", fixedContent);


  // **************** Digest content using sha-256 & encode it to base-64
  nodeDigestValue.textContent = digestWithHash(fixedContent)
    .toString('base64')
    .trim();

  return doc;
}

Here is the main problem I already tried package called C14N as you can see in the code but still getting same error result. It also seems doing nothing unless I add replace there

Here is the error that I got from the bank Image

Is there any implementation in javascript to generate this SignedXML? I already search everywhere & most of them are either still stuck in INI & HIA or is in different programming language

NodeJs version: v20.14.0

 "@xmldom/xmldom": "^0.8.10",
"archiver": "^7.0.1",
"axios": "^1.7.2",
"luxon": "^3.4.4",
"node-forge": "^1.3.1",
"uuid": "^10.0.0",
"xml-crypto": "^4.0.1",
"xpath": "0.0.32"

Thank you :)


Solution

  • the problem is on canonicalization process

    I just need to add more attributes & it can send HPB after that

      const contentToSign = new C14n()
      .process(select('//ds:SignedInfo', doc)[0])
      .replace(
        'xmlns:ds="http://www.w3.org/2000/09/xmldsig#"',
      'xmlns="urn:org:ebics:H004" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
    )