Why is my signed XML getting rejected by authorization?

130
July 27, 2022, at 05:30 AM

I'm trying to create a signed XML post request. The XML needs to be sent in the body of the request. The signing needs to have the following:

  1. The digest needs to have inclusive canonicalization algorithm
  2. The signature needs to have exclusive canonicalization algorithm
  3. The syntax enveloped signature must be used
  4. SHA-256 needs to be used for hashing
  5. The digital signature needs to be RSAWithSHA256 algorithm with 2048 bits
  6. The fingerprint needs to be an X.509 certificate. The fingerprint can be calculated with the following formula: HEX(SHA-1(DER certificate))

All these requirements are coming straight out of the documentation.

I have used xml-crypto for signing the XML The .cer en .pem file are created with the following commands:

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.pem -out certificate.cer

The code below I have used for signing the XML.

const xml = `<?xml version="1.0" encoding="UTF-8"?>
            <someTag xmlns="some_url" version="3.3.1">
                <createDateTimestamp>${new Date().toISOString()}</createDateTimestamp>
                <anotherTag>
                    <id>${id}</id>
                    <subID>0</subID>
                </anotherTag>
            </someTag>`;
        try {  
            // certificate file
            const cer = Buffer.from((await bucket.file(`certificates/certificate.crt`).download())[0]).toString('base64');
            logger.log('pem', cer.toString());
            const cerShasum = crypto.createHash('sha1');
            cerShasum.update(cer);
            // private key file
            const pem = Buffer.from((await bucket.file(`certificates/privateKey.pem`).download())[0]);
            logger.log('pem', pem.toString());
            // const decryptedKey = forge.pki.decryptRsaPrivateKey(pem.toString('ascii'), pemPassphrase);
            // const decryptedKeyBuffer = Buffer.from(forge.pki.privateKeyToPem(decryptedKey), 'ascii');
            // logger.log('decryptedKeyBuffer', decryptedKeyBuffer.toString());
            // sign xml document
            const sig = new SignedXml();
            sig.signingKey = pem;
            sig.signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'; // set signing algorithme
            sig.addReference('//*[local-name()="someTag"]', ['http://www.w3.org/2000/09/xmldsig#enveloped-signature'], 'http://www.w3.org/2001/04/xmlenc#sha256');
            sig.keyInfoProvider = new FileKeyInfo(); 
            logger.log('xml', xml);
            sig.computeSignature(xml);
            let postData = sig.getSignedXml();
            postData = postData.replace('<X509Data/>', `<KeyName>${cerShasum.digest('hex')}</KeyName>`).replace('#_0', '').replace('Id="_0"', '').trim(); 
            logger.log('postData', postData);
            // sent req
            const url = host;
            const result = await axios.post(url, postData);
            logger.log('result', result);
            logger.log('res.data', result.data);
            const resDataJson = await parseStringPromise(result.data);
            logger.log('resDataJson', resDataJson);
        } catch (e) {
            logger.error('error: ', e);
        }

And the error I got:

<Error>
        <errorCode>SE2000</errorCode>
        <errorMessage>Authentication error</errorMessage>
        <errorDetail>Field generating error: Signature</errorDetail>
 </Error>

When I try to validate the signature to an checker I get the following error

func=xmlSecOpenSSLEvpDigestVerify:file=digests.c:line=279:obj=sha256:subj=unknown:error=12:invalid data:data and digest do not match
RESULT: Signature is INVALID

Is the problem that the DigestValue is not being generated properly?

Does anybody see what I'm doing wrong?

Answer 1
sig.computeSignature(xml);
            let postData = sig.getSignedXml();
            postData = postData.replace('<X509Data/>', `<KeyName>${cerShasum.digest('hex')}</KeyName>`).replace('#_0', '').replace('Id="_0"', '').trim(); 
            logger.log('postData', postData);

So you firstly compute the signature and after modify its content? This will break the computed signature. Secondly, it seems like the signature you send does not include the originally signed content, therefore the validator is not able to de-reference the signed data and correctly compare the digests.

More likely, you want to use either an enveloped signature format or enveloping. For more information please see XMLDSig specification.

Rent Charter Buses Company
READ ALSO
What library can I use to generate random mock data based on Open API spec inside a node application?

What library can I use to generate random mock data based on Open API spec inside a node application?

I am looking for a library which would generate a mock data based on openapi spec (client side only)So the idea is not to have a separate local server, as it's done in openapi-mock-express-middleware, but rather have data to be generated on fly inside...

91
TypeError: models[model].defineConstraints is not a function

TypeError: models[model].defineConstraints is not a function

I`m trying to undestand whats going on and why defineConstraints is not a functioncan someone help me ?

79
use nodejs var as json object statement?

use nodejs var as json object statement?

how do I use a nodejs var inside a json statement, I dont realy have the required vocabulary to explain but here is my simplifyed code:

97
Store files on mongodb database or server

Store files on mongodb database or server

I have a website built on MongoDB which has files to be downloaded by users other than images ( it can be a software installer orexe file

71