1

我签署的文件是这样的。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="CDA_PL_IG_1.3.1.xsl" type="text/xsl"?>
<ClinicalDocument></ClinicalDocument>

我正在使用xadesjs以下代码对此 XML 进行签名:

const crypto = new Crypto();
xadesjs.Application.setEngine('NodeJS', crypto);

export async function sign(xml: string, { publicKey, privateKey }: any) {
    const hash = 'SHA-1';
    const alg = {
        name: 'RSASSA-PKCS1-v1_5',
        hash
    };
    const keyDer = pem2der(privateKey.toString());
    const key = await crypto.subtle.importKey('pkcs8', keyDer, alg, true, [ 'sign' ]);
    const parsed = xadesjs.Parse(xml.trim());
    const xadesXml = new xadesjs.SignedXml();
    const signature = await xadesXml.Sign(alg, key, parsed, {
        signingCertificate: preparePem(publicKey.toString()),
        references: [ { uri: '', hash, transforms: [ 'enveloped' ] } ],
        x509: [ preparePem(publicKey.toString()) ]
    });

    parsed.documentElement.appendChild(signature.GetXml()!);
    return parsed.toString();
}

function preparePem(pem: string) {
    return pem.replace(/-----(BEGIN|END)[\w\d\s]+-----/g, '').replace(/[\r\n]/g, '');
}

function pem2der(pem: string) {
    pem = preparePem(pem);
    return new Uint8Array(Buffer.from(pem, 'base64')).buffer;
}

仅当我删除 xml 声明和样式表指令时,生成的签名才有效。因此,仅签署此文件会返回正确签署的文档:

<ClinicalDocument></ClinicalDocument>

签署这个

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="CDA_PL_IG_1.3.1.xsl" type="text/xsl"?>
<ClinicalDocument></ClinicalDocument>

错误消息说不是整个文档都已签名。

我认为问题出在URI=""参考上。它只签名并<ClinicalDocument>留下不签名。<?xml version><?xml-stylesheet>

我如何签署所有内容?

4

1 回答 1

3

在签署之前,您需要规范化 (C14N) 文档。我无法评论使用 xadesjs,但这里有一些一般性建议。

对于 Xades 签名,您需要计算一个包含三个部分的消息摘要,所有这些部分都是 C14N-ed。

(1) 不包括元素的完整文档ds:Signature- 这为您提供了URI=""参考的摘要值。

(2)xades:SignedProperties元素的子集,需要从完整文档中继承任何命名空间。这给出了 SignedProperties 引用的摘要值。

(3)ds:SignedInfo元素的最后一个子集,它再次需要包括继承的命名空间——这个值被间接用于计算签名值。

<?xml version>总是被排除在外。<?xml-stylesheet>计算封装签名的摘要值时包括在内(参考 URI=""),但在对两个子集进行 C14N 处理时不包括在内。

计算 C14n 变换并非易事。我将在这里插入我自己的规范化实用程序 SC14N https://www.cryptosys.net/sc14n/

您可以直接生成摘要值,如下所示:

sc14n -d -x ds:Signature clindoc.xml
sc14n -d -s xades:SignedProperties clindoc.xml
sc14n -d -s ds:SignedInfo clindoc.xml

要查看 C14N 版本的输出,请省略 -d 选项

sc14n  -x ds:Signature clindoc.xml
<?xml-stylesheet href="CDA_PL_IG_1.3.1.xsl" type="text/xsl"?>
<ClinicalDocument ...>

请注意,该<xml-stylesheet行包含在自己的行中。

于 2020-01-07T01:00:55.853 回答