It is generally useful to be able to move signed resources without breaking signatures on the data. As long as the resource can still be obtained by a given Location, it should be verifiable. Also, it will often be necessary to change the Transforms applied to the data since Transforms help to locate the data and, as well, the data may be stored in a different format in its new location.
P.S. Many have expressed concern about the solution proposed in this document, which is to apply Transforms to SignedInfo. The following notes apply:
The point of this list is that you don't have to agree with Transforms on SignedInfo to take something meaningful out of this document. These scenarios are problems that people have that we must either decide not to solve or decide to solve in some way. The SignedInfo Transforms describe what needs to be omitted from SignedInfo under the assumption that an ObjectReference's Location and Transforms are more than just hints for the verifier.
If a signature is expected to be verifiable after the indicated resource is moved to a new web location, then there must be a way of changing how the resource is retrieved. Deferring to application-specific URN processing rules may not suffice given the frequency with which this situation occurs on the web. An alternative is to allow a Transforms element to process the SignedInfo.
<Signature>
<SignedInfo>
<CanonicalizationMethod...
<!-- This can go in the following Transforms -->
<Transforms> <!-- On SignedInfo -->
<Transform Algorithm="&XPath;">
descendant-or-self::node()[
not(self::Location and parent::ObjectReference)]
</Transform>
</Transforms>
<SignatureMethod...
<ObjectReference Location="http://some.org/some.doc">
<DigestMethod...
<DigestValue...
</ObjectReference>
</SignedInfo>
<SignatureValue...
</Signature>
Since the Location is omitted from the SignedInfo, if the resource is moved, the Location attribute can be changed without breaking the signature.
It is useful for applications to put a number of signed records (perhaps the result of a database search) into the same XML file for delivery to a user without breaking the signatures on the individual records.
This can be accomplished by Id attribute omission in conjunction with omitting a small part of the Transforms of the ObjectReference. Specifically, if text of the the barename XPointer that identifies the element to be digested should be omitted. This will allow us to change that record name to DefendantRecord1, DefendantRecord2, etc.
<Signature>
<SignedInfo>
<CanonicalizationMethod...
<!-- This can go in the following Transforms -->
<Transforms> <!-- On SignedInfo -->
<Transform Algorithm="&XPath;">
descendant-or-self::node()[
not(self::text() and
ancestor::Transform[ancestor::ObjectReference[3] and
parent::Transform[@Algorithm="&XPtr;"])]
</Transform>
</Transforms>
<SignatureMethod...
<ObjectReference Location="">
<Transforms>
<Transform Algorithm="&XPtr;">DefendantRecord</Transform>
<Transform Algorithm="&XPath;">
descendant-or-self::node()[not(self::Id)]</Transform>
</Transforms>
<DigestMethod...
<DigestValue...
</ObjectReference>
</SignedInfo>
<SignatureValue...
</Signature>
<Record Id="DefendantRecord">
<name>Someone Guilty</name>
<address>#3 Death Row</address>
<status>appeal of conviction</status>
...
</Record>
If a database search yielded a number of these records, then placing them in a single file for return to the user would require changing each Id to something unique due to rules of XML. This can be done if the Id attribute is omitted from the message whose digest is placed in the DigestValue of ObjectReference and if the text of the XPointer Transform in the ObjectReference is omitted from the SignedInfo before its digest is calculated and placed in SignatureValue.
Actually, the XPath transform of SignedInfo could be even more explicit. The XPath could restrict the omission to being the first Transform in the ObjectReference's Transforms, and it could even do some string matching on the contents of the text before deciding to omit it.
This is a case of applying the notion of DOCUMENT CLOSURE to SignedInfo. As long as the SignedInfo Transforms are signed, we can guarantee that the small bit of data omitted from ObjectReference Transforms does not break security even though it is not covered by the digest.
A comprehensive scenario uses the XML signature as an envelope for delivery of data to the desktop. Once at the desktop, the data must be unenveloped and detached from the signature for use by applications.
In this case, the signature will be retained for future use, but it must be changed to indicate the new external location of the signed data, and the enveloped copy of the data will be deleted.
In this first signature, the data is base64 encoded and enveloped in an element called DATA1. The Transforms in the ObjectReference recover the original binary data on which the digest will be calculated.
The Transforms outside of the ObjectReference represent the proposed method for helping to solve this problem. Since the Location and Transforms must be changed when the data is moved outside of the enveloping Object, they are omitted from the SignedInfo.
<Signature>
<SignedInfo>
<CanonicalizationMethod...
<!-- This can go in the following Transforms -->
<Transforms> <!-- On SignedInfo -->
<Transform Algorithm="&XPath;">
descendant-or-self::node()[
not(self::Location and parent::ObjectReference) and
not(Exact description of the base 64 and Xpath transforms below)]
</Transform>
</Transforms>
<SignatureMethod...
<ObjectReference Location="">
<Transforms>
<Transform Algorithm="&XPath;">
descendant::text()[parent::node()[@Id="DATA1"]]
</Transform>
<Transform Algorithm="&base64;"/>
</Transforms>
<DigestMethod...
<DigestValue...
</ObjectReference>
</SignedInfo>
<SignatureValue...
<Object Id="DATA1" Encoding="&base64;">
ABCDEFGHIJKLMNOPQRSTUVWXYZ...
</Object>
</Signature>
When the data is moved to disk in natural binary format, the Location can be changed to indicate the local file, and the specific Transforms in ObjectReference are no longer necessary:
<Signature>
<SignedInfo>
<CanonicalizationMethod...
<!-- This can go in the following Transforms -->
<Transforms> <!-- On SignedInfo -->
<Transform Algorithm="&XPath;">
descendant-or-self::node()[
not(self::Location and parent::ObjectReference) and
not(ancestor::Transforms[parent::ObjectReference])]
</Transform>
</Transforms>
<SignatureMethod...
<ObjectReference Location="file:filename">
<DigestMethod...
<DigestValue...
</ObjectReference>
</SignedInfo>
<SignatureValue...
</Signature>