1

The document I am signing looks like this.

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

I am using xadesjs to sign this XML with the following code:

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;
}

The generated signature is valid only if I remove the xml declaration and stylesheet instruction. So only signing this returns a correctly signed document:

<ClinicalDocument></ClinicalDocument>

Signing this

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

errors with message saying that not the entire document is signed.

I assume the problem is with the URI="" reference. It signs only the <ClinicalDocument> and leaves the <?xml version> and <?xml-stylesheet> with no signature.

How do I sign everything?

Tomasz Kula
  • 16,199
  • 2
  • 68
  • 79
  • Years ago when I studied xades I was Not able to sign something outside root xml element. If you want an exact sign, byte per byte, why dont you use CADES? Just my 2 cents – abatti Jan 04 '20 at 18:02
  • Unfortunately, it's not up to me to pick the signature. I have to use XADES for this. – Tomasz Kula Jan 06 '20 at 16:57

1 Answers1

3

You need to canonicalize (C14N) the document before you sign it. I cannot comment on using xadesjs but here is some general advice.

For a Xades signature you need to compute a message digest over three parts, all of them C14N-ed.

(1) the full document excluding the ds:Signature element - this gives you the digest value for the URI="" reference.

(2) The subset of the xades:SignedProperties element, which needs to inherit any namespaces from the full document. This gives the digest value for the SignedProperties reference.

(3) The final subset of the ds:SignedInfo element, which again needs to include inherited namespaces - this value is used indirectly to compute the signature value.

The <?xml version> is always excluded. The <?xml-stylesheet> is included when computing the digest value for the enveloped-signature (with reference URI="") but is excluded when C14N-ing over the two subsets.

Computing the C14n transformation is not trivial. I will plug my own canonicalization utility here, SC14N https://www.cryptosys.net/sc14n/.

You can generate the digest values directly as follows:

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

To see the C14N-ed output, omit the -d option

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

Note that the <xml-stylesheet line is included on a line of its own.

David I
  • 881
  • 6
  • 10
  • Thanks a lot for the answer. After additional research it looks like a bug in canonization process in the xmldsigjs library which is a direct dependency of xadesjs and is responsible for the canonization process. https://github.com/PeculiarVentures/xadesjs/issues/94#issuecomment-571694427 – Tomasz Kula Jan 08 '20 at 07:50