【问题标题】:Why is my signed XML getting rejected by authorization?为什么我的签名 XML 被授权拒绝?
【发布时间】:2022-07-25 03:57:50
【问题描述】:

我正在尝试创建一个签名的 XML 发布请求。 XML 需要在请求的正文中发送。 签名需要具备以下条件:

  1. 摘要需要具有包容性规范化算法
  2. 签名需要有专属的规范化算法
  3. 必须使用语法封装签名
  4. SHA-256 需要用于散列
  5. 数字签名需为2048位的RSAWithSHA256算法
  6. 指纹需要是 X.509 证书。指纹计算公式如下:HEX(SHA-1(DER certificate))

所有这些要求都直接来自文档。

我使用 xml-crypto 来签署 XML .cer en .pem 文件是使用以下命令创建的:

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

下面的代码用于签署 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);
        }

我得到的错误:

<Error>
        <errorCode>SE2000</errorCode>
        <errorMessage>Authentication error</errorMessage>
        <errorDetail>Field generating error: Signature</errorDetail>
 </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

是DigestValue没有正确生成的问题吗?

有人看到我做错了吗?

【问题讨论】:

    标签: node.js xml xml-signature


    【解决方案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);
    

    所以你首先计算签名,然后修改它的内容?这将破坏计算的签名。 其次,您发送的签名似乎不包含原始签名内容,因此验证器无法取消引用签名数据并正确比较摘要。

    更有可能的是,您想使用信封签名格式或信封。有关详细信息,请参阅XMLDSig 规范。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-01
      • 2016-03-17
      • 2011-03-29
      • 1970-01-01
      • 2011-08-28
      相关资源
      最近更新 更多