Open QAnders opened 3 years ago
I'll share my code as well which works now and signature is validated using xmlsec1
. I send in the certificates in PEM
(CER
) format (base64 with the BEGIN/END headers/footers).
const { XMLSerializer } = require('xmldom-alpha');
const xmldsigjs = require('xmldsigjs');
const { Crypto } = require('@peculiar/webcrypto');
const crypto = new Crypto();
xmldsigjs.Application.setEngine('NodeJS', crypto);
function preparePem(pem) {
return (
pem
// remove BEGIN/END
.replace(/-----(BEGIN|END)[\w\d\s]+-----/g, '')
// remove \r, \n
.replace(/[\r\n]/g, '')
);
}
function pem2der(pem) {
pem = preparePem(pem);
// convert base64 to ArrayBuffer
return new Uint8Array(Buffer.from(pem, 'base64')).buffer;
}
async function signXML(xmlString, publicKeyPem, privateKeyPem) {
// const fs = require('fs');
const hash = 'SHA-1';
const alg = {
name: 'RSASSA-PKCS1-v1_5',
hash,
publicExponent: new Uint8Array([1,0,1]),
modulusLength: 2048,
};
const keyDer = pem2der(privateKeyPem);
const key = await crypto.subtle.importKey('pkcs8', keyDer, alg, false, [
'sign'
]);
let xml = xmldsigjs.Parse(xmlString);
let digSigXml = new xmldsigjs.SignedXml();
const X509Data = new xmldsigjs.KeyInfoX509Data();
X509Data.AddSubjectName(process.env.SMP_QVALIA_CN);
digSigXml.XmlSignature.KeyInfo.Add(X509Data);
const signature = await digSigXml.Sign(
// Signing document
alg, // algorithm
key, // key
xml, // document
{
// options
references: [
{
hash,
transforms: ['enveloped']
},
],
x509: [preparePem(publicKeyPem)],
signingCertificate: preparePem(publicKeyPem)
}
);
// append signature
xml.documentElement.appendChild(signature.GetXml());
// serialize XML
const oSerializer = new XMLSerializer();
const sXML = oSerializer.serializeToString(xml);
// fs.writeFileSync("/home/anders/CodeStuff/signed3.xml", sXML.toString());
return sXML.toString();
}
So this is not a bug?
Your post made it sound like you solved your problem?
Ah, no, sorry if I'm being a pain... I just wanted to add my code in full incase I am missing something...
I meant that it is producing valid signatures IF I don't have any namespace prefix on the root element.
Is this one dea, or something someone is looking at?
As I understand it the signature validates with xmlsec1 but the other tool your using doesn’t like it.
this would require us to 1) have an example of a file it does like, 2) have access to the tool
We are also experiencing this issue. We validated using multiple tools, and having a namespace prefix in the root element causes validation issues.
Use an online validator like: https://tools.chilkat.io/xmlDsigVerify.cshtml
Steps to re-create The below example succeeds when using no root namespace prefixes
<InitSessionSignedRequest
xmlns="http://example.com/online/types/2021/10/01/0001"
xmlns:ns2="http://example.com/types/2021/10/01/0001"
xmlns:ns3="http://example.com/online/auth/request/2021/10/01/0001">
</InitSessionSignedRequest>
The below example fails when using a root prefix:
<ns3:InitSessionSignedRequest
xmlns="http://example.com/online/types/2021/10/01/0001"
xmlns:ns2="http://example.com/types/2021/10/01/0001"
xmlns:ns3="http://example.com/online/auth/request/2021/10/01/0001">
</ns3:InitSessionSignedRequest>
We tried multiple permutations and transforms, and the issue appears related to how the XML (and prefix) root is being handled in this library.
Working through my issues trying to solve the Peppol (Peppol.eu) standard signature I realized that the signature becomes invalid if the root element has a namespace prefix...
This snippet generates a valid signature:
But adding the prefix to the root generates a invalid signature: