diff --git a/README.md b/README.md index 9346784c..4f822e50 100644 --- a/README.md +++ b/README.md @@ -71,15 +71,22 @@ string is parsed into a new document and the next transform is applied to that, [reference processing model](https://www.w3.org/TR/xmldsig-core1/#sec-ReferenceProcessingModel) requires. Every built-in canonicalization algorithm returns a string, so: -- `enveloped-signature` after a canonicalization removes the `Signature`, including one inside the - referenced element. -- The result of a `#WithComments` canonicalization followed by `enveloped-signature` is - [canonicalized](#transforms-that-end-in-a-dom-node) without comments. - Exclusive canonicalization after inclusive canonicalization omits inherited namespace declarations that the referenced element does not use. - A custom transform after a canonicalization receives the parsed document. - A transform throws when the string returned by the transform before it is not well-formed XML. +`enveloped-signature` is the exception. XMLDSig applies it only to +[a node-set from its parent XML document](https://www.w3.org/TR/xmldsig-core1/#sec-EnvelopedSignature), +which the parsed document is not, so list `enveloped-signature` before any canonicalization. Applying +it after a transform that returns a string is deprecated, when signing and when verifying, and will +throw in 7.0. Until then it prints a `DeprecationWarning`, and: + +- `enveloped-signature` after a canonicalization removes the `Signature`, including one inside the + referenced element. +- The result of a `#WithComments` canonicalization followed by `enveloped-signature` is + [canonicalized](#transforms-that-end-in-a-dom-node) without comments. + ### Copies of an enveloped signature The `enveloped-signature` transform removes only the `Signature` element being verified, as @@ -125,6 +132,9 @@ deprecated and stay exported. `getReferences()` and `references` are deprecated. Do not use them to obtain signed XML; use `getSignedReferences()` instead, as shown in [Verifying Xml documents](#verifying-xml-documents). +`enveloped-signature` after a transform that returns a string is deprecated; see +[Transforms that follow a canonicalization](#transforms-that-follow-a-canonicalization). + ## Supported Algorithms ### Canonicalization and Transformation Algorithms diff --git a/src/signed-xml.ts b/src/signed-xml.ts index 841e23c1..d181c6b8 100644 --- a/src/signed-xml.ts +++ b/src/signed-xml.ts @@ -90,6 +90,12 @@ const warnValidateElementAgainstReferences = deprecate( "XML_CRYPTO_VALIDATE_ELEMENT_AGAINST_REFERENCES", ); +const warnEnvelopedSignatureAfterCanonicalization = deprecate( + () => {}, + "Applying `enveloped-signature` after a transform that returns a string, such as a canonicalization, is deprecated and will throw in a future version. List `enveloped-signature` before any canonicalization in the `Reference`.", + "XML_CRYPTO_ENVELOPED_SIGNATURE_AFTER_CANONICALIZATION", +); + export class SignedXml { idMode?: "wssecurity"; idAttributes: string[]; @@ -1444,6 +1450,7 @@ export class SignedXml { } let transformedXml: Node | string = canonXml; let transformOptions = options; + let parsedFromOctets = false; // Octets are parsed into a node-set for the next transform, and a node-set left at the end is // converted to octets with C14N: https://www.w3.org/TR/xmldsig-core1/#sec-ReferenceProcessingModel @@ -1458,6 +1465,15 @@ export class SignedXml { defaultNs: "", signatureNode: this.findLoadedSignature(transformedXml) ?? options.signatureNode, }; + parsedFromOctets = true; + } + // enveloped-signature takes only a node-set from its parent document: + // https://www.w3.org/TR/xmldsig-core1/#sec-EnvelopedSignature + if ( + parsedFromOctets && + transformName === "http://www.w3.org/2000/09/xmldsig#enveloped-signature" + ) { + warnEnvelopedSignatureAfterCanonicalization(); } // Each transform takes only the parameters of its own Transform: // https://www.w3.org/TR/xmldsig-core1/#sec-Transforms