-
Notifications
You must be signed in to change notification settings - Fork 189
Open
Description
Can someone help me to generate same signature like this in nodejs using xml-crypto:
I have two keys :
- privatekey.pem
- publickey.pem
<Req
xmlns="http://www.abc.com/abc/schema/">
<Header requestId="f359718a-b759-4617-aebb-1260d98fef3e" timestamp="2025-01-19 15:26:28.552" ver="1.0"/>
<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>RX4gMUYcjhYtNPANxPJ2aCmxXzc=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>fptL80Jl6614.....</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>hPN+z6tI/WSPV1sKDDfw2.....</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature>
</Req>
This is my try in js
const crypto = require('crypto');
const SignedXml = require('xml-crypto').SignedXml;
const fs = require('fs').promises;
class XmlSigner {
constructor() {
this.XML_TEMPLATE = `<Req
xmlns="http://www.abc.com/abc/schema/">
<Header requestId="f359718a-b759-4617-aebb-1260d98fef3e" timestamp="2025-01-19 15:26:28.552" ver="1.0"/></Req>`;
}
async loadPrivateKey(pemContent) {
return pemContent.replace('-----BEGIN PRIVATE KEY-----', '').replace('-----END PRIVATE KEY-----', '').replace(/\s/g, '');
}
async loadPublicKey(pemContent) {
return pemContent.replace('-----BEGIN PUBLIC KEY-----', '').replace('-----END PUBLIC KEY-----', '').replace(/\s/g, '');
}
extractModulusAndExponent(publicKeyPem) {
// Create a public key object
const publicKey = crypto.createPublicKey({
key: `-----BEGIN PUBLIC KEY-----\n${publicKeyPem}\n-----END PUBLIC KEY-----`,
format: 'pem'
});
// Export as DER format
const derKey = publicKey.export({ type: 'spki', format: 'der' });
// Parse the DER structure to extract modulus and exponent
// Skip the ASN.1 header to get to the key parts
let offset = 24; // Typical offset for RSA public key in SPKI format
// Read modulus length
const modulusLength = derKey[offset];
offset++;
// Extract modulus
const modulus = derKey.slice(offset, offset + modulusLength);
offset += modulusLength;
// Skip header byte
offset++;
// Read exponent length
const exponentLength = derKey[offset];
offset++;
// Extract exponent
const exponent = derKey.slice(offset, offset + exponentLength);
return {
modulus: modulus.toString('base64'),
exponent: exponent.toString('base64')
};
}
async signXml(privateKeyPem, publicKeyPem) {
const { modulus, exponent } = this.extractModulusAndExponent(publicKeyPem);
const sig = new SignedXml();
sig.addReference({
xpath: "/*",
digestAlgorithm: 'http://www.w3.org/2000/09/xmldsig#sha1',
transforms: ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],
isEmptyUri: false,
});
sig.canonicalizationAlgorithm = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
sig.signatureAlgorithm = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
sig.privateKey = Buffer.from(privateKeyPem, 'base64');
sig.keyInfo = `<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><KeyValue><RSAKeyValue><Modulus>${modulus}</Modulus><Exponent>${exponent}</Exponent></RSAKeyValue></KeyValue></KeyInfo>`;
console.log(this.XML_TEMPLATE);
sig.computeSignature(xml, signature);
return sig.getSignedXml();
}
}
async function main() {
try {
const signer = new XmlSigner();
// Load keys from files
const privateKeyPem = await fs.readFile('private_key.pem', 'utf8');
const publicKeyPem = await fs.readFile('public_key.pem', 'utf8');
// Load and process the keys
const privateKey = await signer.loadPrivateKey(privateKeyPem);
const publicKey = await signer.loadPublicKey(publicKeyPem);
// Sign the XML
const signedXml = await signer.signXml(privateKey, publicKey);
console.log(signedXml);
} catch (error) {
console.error('Error:', error);
console.error('Stack:', error.stack);
}
}
main();
Metadata
Metadata
Assignees
Labels
No labels