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(/
/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
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 🙂