Tag 296 (sharedref-namespace) Data Item any Semantics isolate shared values within this scope Reference https://cbor.is4.site/sharedref-namespace Contact IS4 <is4.site@gmail.com>
This tag is used to restrict the visibility of shareable values (using tag 28
) to the scope of the value in this tag, similarly to how tag 256
(stringref-namespace) can be used to isolate string references.
Existing tags 28
(shareable) and 29
(sharedref) are used to refer to an identical object from multiple places by identifying a value using an auto-incremented index.
The issue with this mechanism is that a single space of identifiers is used for all marked values during the decoding process, which requires adjusting the references when CBOR objects are composed or sequenced, and prevents simple binary concatenation of CBOR values.
By explicitly establishing a namespace of shared values, references within such names do not depend on any previous marked values in the CBOR stream, and marking shareable values within it does not affect the rest of the CBOR stream after the namespace.
The sharedref-namespace tag (value 296
) establishes an explicit scope of shared values, affecting any value tagged as shareable (value 28
) or sharedref (value 29
) within the tag. The modification to the behaviour of these two tags is as follows:
28
) is relative to the innermost scope of shared values that encloses it. That is, the first such value is assigned the index 0, the next index 1, and so on, irrespective of any value of the index counter at the point when the namespace was encountered. Additionally, marking a value as shareable in a scope does not affect any of the namespaces enclosing that scope.29
) identifies a shareable value whose index has been assigned within the innermost scope of shared values enclosing the reference. That is, the index 0 refers to the first value in the same innermost scope of shared values, the index 1 refers to the second such value, and so on. Values that were shared in other scopes are not accessible by this mechanism.In practical terms, this means that any arbitrary sharedref-namespace-tagged value may be inserted in the CBOR stream (while maintaining well-formedness) without any effect on the decoding of any shared values that follow it, and without previous shared values affecting those within the sharedref-namespace tag. That is, the tag fully isolates its content from any external data in terms of value sharing (tags 28
and 29
).
The interpretational value of this tag is the same as that of the value stored within it. Wrapping the whole CBOR stream in sharedref-namespace, i.e. replacing the implicit scope of shared values with an explicit one, should have no observable effect on the interpretation of such a stream. Likewise, removing all sharedref-namespace tags in a CBOR stream, while ensuring shared references in previously isolated namespaces do not overlap and still refer to identical values, should have no observable effect on the interpretation of such a stream.
As these tags may be arbitrarily nested within each other, decoders need to preserve information about namespaces enclosing the current scope in order to restore them when the scope ends. Architecturally, the implementation should be similar to that of stringref-namespace (value 256
). Unlike that tag, however, using the sharedref-namespace in a CBOR stream containing shareable values or references thereto is completely optional, and only serves to establish isolated scopes within such stream.
The following is an example of 3 arrays stored alongside each other, each containing an object in its first index shared to the second index.
[ [28({}), 29(0)], [28({}), 29(1)], [28({}), 29(2)] ]
83 # array(3) 82 # array(2) D8 1C # tag(28) A0 # map(0) D8 1D # tag(29) 00 # unsigned(0) 82 # array(2) D8 1C # tag(28) A0 # map(0) D8 1D # tag(29) 01 # unsigned(1) 82 # array(2) D8 1C # tag(28) A0 # map(0) D8 1D # tag(29) 02 # unsigned(2)
Even though these arrays are fundamentally equivalent, their binary encoding is not interchangeable. However, wrapping each of them in its individual namespace fixes this issue:
[ 296([28({}), 29(0)]), 296([28({}), 29(0)]), 296([28({}), 29(0)]) ]
83 # array(3) D9 0128 # tag(296) 82 # array(2) D8 1C # tag(28) A0 # map(0) D8 1D # tag(29) 00 # unsigned(0) D9 0128 # tag(296) 82 # array(2) D8 1C # tag(28) A0 # map(0) D8 1D # tag(29) 00 # unsigned(0) D9 0128 # tag(296) 82 # array(2) D8 1C # tag(28) A0 # map(0) D8 1D # tag(29) 00 # unsigned(0)
Each occurrence of 29(0)
identifies the map preceding it, as it is the first marked value in its respective namespace.
As this tag is usable only in combination with tags 28
and 29
, the same security considerations as for those tags apply. Establishing isolated scopes of shared values does not have any impact on the security of these tags.