| Internet-Draft | SMD-CWT | October 2026 |
| Maldant | Expires 29 April 2027 | [Page] |
This document specifies an extension to Selective Disclosure CBOR Web Tokens (SD-CWT) that reduces their size and improves their privacy properties. In this extension, the individual hashes of the redacted claims of a map or an array are replaced with the root hash of a Merkle tree, and disclosed claims are presented with a Merkle proof.¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://beltram.github.io/draft-maldant-spice-smd-cwt/draft-maldant-spice-smd-cwt.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-maldant-spice-smd-cwt/.¶
Discussion of this document takes place on the Secure Patterns for Internet CrEdentials Working Group mailing list (mailto:spice@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/spice/. Subscribe at https://www.ietf.org/mailman/listinfo/spice/.¶
Source for this draft and an issue tracker can be found at https://github.com/beltram/draft-maldant-spice-smd-cwt.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 29 April 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
This document defines Selective Merkle Disclosure CBOR Web Tokens (SMD-CWT), an extension to SD-CWT [SD-CWT].¶
SD-CWT provides an efficient mechanism by which a Holder controls which claims it presents to a Verifier, thereby improving the privacy of the Holder. However, when the presentation is sparse and only a subset of the claims is disclosed, a Verifier learns the total number of claims, reducing the privacy benefit of selective disclosure. Furthermore, each redacted claim adds 34 bytes to the presented token (SD-KBT), even though the claim itself is not disclosed to the Verifier.¶
To address both issues, this document specifies that, rather than hashing each claim individually and placing the resulting hashes in a CBOR array, the claims of each map or array are placed in a Merkle tree and only the root hash of that tree is included in the SD-CWT. A presentation of the token then includes only a Merkle proof attesting to the integrity of the disclosed claims. The size of this proof is logarithmic in the number of claims, whereas the size of an enumeration of all redacted claims is linear in that number.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The CBOR examples in this document are shown in CBOR Extended Diagnostic Notation (EDN) [I-D.ietf-cbor-edn-literals].¶
Data model constraints are described using the Concise Data Definition Language (CDDL) [RFC8610].¶
This document uses terms from CWT [RFC8392], COSE [RFC9052] [RFC9053], and JWT [RFC7519].¶
The terms Claim Name, Claim Key, and Claim Value are defined in [RFC8392].¶
This document defines the following terms:¶
An SD-CWT containing claims that can be selectively disclosed using a Merkle proof.¶
An SD-KBT used to demonstrate possession of a confirmation method and to present claims with a Merkle proof.¶
For a given leaf of a Merkle tree, the siblings of the nodes on the path from that leaf to the root.¶
All other terms used in this document have the meaning defined in [SD-CWT].¶
SMD-CWT is an extension of SD-CWT: every SD-CWT is a valid SMD-CWT, but an SMD-CWT is not necessarily a valid SD-CWT. The two differ only in the way redacted claims are authenticated and presented.¶
An SD-CWT Issuer enumerates the hashes of all redacted claims, either in the redacted_claim_keys array of a map, or in
place of the redacted elements of an array. In contrast, an SMD-CWT Issuer places these hashes at the leaves of a
left-balanced Merkle tree and replaces the set of claims in the original payload with the root hash of that tree.¶
A Holder then selectively presents claims to a Verifier in an SMD-KBT by replacing the disclosed claims with proofs of their inclusion in the Merkle tree. The root hash of that tree is authenticated by the Issuer in the SMD-CWT.¶
An SMD-CWT Issuer is also an SD-CWT Issuer: it MUST be capable of encoding and signing a regular SD-CWT when requested and, in addition, supports the generation of SMD-CWTs.¶
Figure 1 shows an example CWT payload. Common claims are omitted for brevity.¶
{
"most_recent_inspection_passed": true,
"inspector_license_number": "ABCD-123456",
"inspection_dates" : [
1549560720, / 2019-02-07T17:32:00 /
1612498440, / 2021-02-04T20:14:00 /
1674004740, / 2023-01-17T17:19:00 /
],
"inspection_location": {
"country": "us", / United States /
"region": "ca", / California /
"postal_code": "94188"
}
}
An SMD-CWT Issuer MUST support the To Be Redacted Tag and the To Be Decoy Tag, both of which are defined in
Section 17.3.1 of [SD-CWT].¶
The To Be Redacted Root Tag (tag 59), defined in Section 10.1.1, indicates to the Issuer that a claim or an array element
is intended to be selectively disclosed with a Disclosure Proof. This tag wraps the element to be redacted in an array
of size 2. The first element of this array is the base-2 logarithm of the size of the Merkle tree used for redaction.
This size MAY be
greater than the number of claims to redact, but MUST NOT be lower.¶
Figure 2 shows the example payload with the corresponding annotations.¶
59([3, { /merkle-redacted of size 8/
"most_recent_inspection_passed": true, /not-redacted/
"inspector_license_number": 58("ABCD-123456"), /redacted/
59([3, "inspection_dates"]) : [ /merkle-redacted of size 8/
58(1549560720), /redacted/
58(1612498440), /redacted/
58(1674004740), /redacted/
],
59([2, "inspection_location"]): { /merkle-redacted of size 4/
"country": 58("us"), /redacted/
"region": 58("ca"), /redacted/
"postal_code": "94188" /not-redacted/
}
}])
For each occurrence of the To Be Redacted Root Tag, at any nesting level, a Merkle tree is built, and all elements of the tagged array or map are placed at its leaves.¶
This specification uses binary Merkle trees similar to those defined in Section 2.1.1 of [RFC9162], with one difference: no domain separation prefix is added to the leaves and the nodes (see Section 4.3). A higher branching factor would provide neither additional benefit nor the desired properties.¶
The Merkle tree is a left-balanced perfect binary tree, as shown in Figure 3. Unbalanced trees are not used, as they are vulnerable to forgery attacks. Perfect binary trees are also easier to represent in memory, and their node indexes are easier to compute, as explained in Appendix C of [RFC9420].¶
In Figure 2, the redaction of the "inspection_location" claim places the "country" claim at node index 0 and the "region" claim at node index 2. Since a size of 2 is requested, the tree has a height of 2 and its last node index is 6, as in Figure 3.¶
Decoys serve a different purpose than in SD-CWT: they do not directly hinder the Verifier's inference of private information. Instead, they act as a blinding factor that prevents a Verifier from inferring the number of leaves, since the hash of a blank leaf is the hash of zero bytes. Decoys are therefore mandatory.¶
Replacing every blank leaf with a Decoy would needlessly inflate the SMD-CWT. Instead, for each node in the Copath of the rightmost entry, the leftmost blank leaf of the subtree rooted at that node MUST be replaced with a Decoy. When the entries fill all the leaves of the tree, no Decoy is added.¶
In Figure 4, the tree contains 9 entries. Decoys (d) are placed as follows:¶
The rightmost entry of the tree is I.¶
Its copath consists of nodes 18, 21, 27, and 7 (_, O, U, and V).¶
For each node in this copath, the leftmost blank leaf of its subtree is replaced with a Decoy. A blank copath node
that is itself a leaf, such as 18, is replaced directly.¶
Consequently, nodes 18, 20, and 24 are replaced with Decoys.¶
The Issuer then computes the root hash of the Merkle tree as follows:¶
Each entry is encoded as a bstr-encoded-salted-merkle-entry, as defined in Figure 9.¶
The resulting bytes are hashed using the hash algorithm indicated by sd_alg in the protected header.¶
The hash of a parent node is the hash of the concatenation of the hashes of its two children, the hash of the left child coming first.¶
This operation is denoted MTH (Merkle Tree Hash), similarly to the one described in Section 2.1.1 of [RFC9162].
Unlike in [RFC9162], no domain separation prefix is added to the leaves and the nodes: since the tree is balanced and
its size is authenticated by the Issuer, all leaves are at the same depth. The MTH of an interior node therefore
cannot be used as the hash of a leaf, and second preimage resistance between leaves and nodes is not required.¶
The root hash is then inserted into the original payload in place of the redacted claims. These claims are declared
within a container, which is either a map or an array. Since the container itself is annotated with the To Be Redacted
Root Tag, it cannot contain regular redacted_claim_keys (simple value 59) or redacted array elements (tag 60).¶
Regardless of the type of the parent container, the root hash is represented as a redacted_root_hash: an array of two
elements, the first of which is the logarithmic size of the Merkle tree producing the root hash, and the second of
which is the root hash itself.¶
redacted_root_hash = [ uint, ; base-2 logarithm of the number of leaves represented in this root hash bstr, ; root hash ]
If the redaction occurs in a map, the redacted_root_hash is placed in the redacted_claim_hash claim.¶
/ redacted_claim_hash / simple(60) : [ uint, bstr ] / redacted_root_hash /
If the redaction occurs in an array, the root hash is placed in an redacted_element_hash element appended to the
array, after the elements that are not redacted.¶
"inspection_dates" : [
1612498440, / item 1 not redacted /
89([ uint, bstr ]) / root hash of item 0 and 2 /
],
Figure 8 shows the disclosure of the inspection_location claim from
Figure 1.¶
<<[
[
/salt/ h'e39612407e99a347d61442957b3dfdac',
/value/ "us",
/claim/ "country"
],
[
/salt/ h'4569990258b25a5267c17a3e3a225ec3',
/value/ "ca",
/claim/ "region"
],
[
/salt/ h'e27403129cd88bf8fee4193e65339a35',
]
]>>
In an SMD-CWT, a Disclosure is an array of all redacted elements of a given container (either a CBOR map or array). Each of these elements has the structure described in Section 3.2 of [SD-CWT], except that they are not individually wrapped in a CBOR bstr (but the outer disclosure is).¶
This Disclosure, along with all other Disclosures, MUST be placed in the sd_claims unprotected header
parameter of the SMD-CWT, as defined in [SD-CWT].¶
; an array of bstr-encoded Salted Disclosed Claims
; in SMD-CWT
salted-merkle-array = [ +bstr-encoded-salted-merkle-entry ]
bstr-encoded-salted-merkle-entry = bstr .cbor salted-merkle-entries
; in SMD-KBT
salted-array-proofs = [ +bstr-encoded-salted-proof ]
bstr-encoded-salted-proof = bstr .cbor disclosure-proof
; where salted-claim, salted-element and decoy are already defined in {{SD-CWT}}
salted-merkle-entry = salted-claim / salted-element / decoy
salted-merkle-entries = [ +salted-merkle-entry ]
; one Merkle proof per presented leaf, ordered by increasing node index
disclosure-proof = [ +merkle-proof ]
merkle-proof = [
redacted-entry,
* bstr ; hash of a copath node, from the leaf up to the root
]
; a presented entry prefixed with the node index of its leaf; Decoys are never presented
redacted-entry = salted-merkle-claim / salted-merkle-element
salted-merkle-claim = [
uint, ; node index of the leaf
bstr .size 16, ; 128-bit salt
any, ; Claim Value
(int / text) ; Claim Key
]
salted-merkle-element = [
uint, ; node index of the leaf
bstr .size 16, ; 128-bit salt
any ; Claim Value
]
; repeated here
salted-claim = [
bstr .size 16, ; 128-bit salt
any, ; Claim Value
(int / text) ; Claim Key
]
salted-element = [
bstr .size 16, ; 128-bit salt
any ; Claim Value
]
decoy = [
bstr .size 16 ; 128-bit salt
]
Figure 10 shows the SMD-CWT issued from Figure 2. Each of the three containers
tagged with the To Be Redacted Root Tag is replaced with a Redacted Root Hash, and its Disclosure is placed in
sd_claims:¶
/ cose-sign1 / 18([ / issuer SMD-CWT /
/ CWT protected / << {
/ alg / 1 : -35, / ES384 /
/ kid / 4 : 'https://issuer.example/cose-key3',
/ typ / 16 : 294, / smd-cwt+sd-cwt (TBD1) /
/ sd_alg / 170 : -16 / SHA256 /
} >>,
/ CWT unprotected / {
/ sd_claims / 17 : [ / these are all the disclosures /
/ top-level claims /
<<[
[
/salt/ h'34821e0250edb1b8aa1e7fcaba161dd5',
/value/ "ABCD-123456",
/claim/ "inspector_license_number"
],
[
/salt/ h'96e374cd67609df517d855e6ad3892f5'
],
[
/salt/ h'dab6a2fe5be976c64c0006d738fca0ef'
],
[
/salt/ h'ae02b9b92e7ca06c3326b357118fcc57'
]
]>>,
/ inspection_dates /
<<[
[
/salt/ h'ad696c9e08b91319073b35c4df54715e',
/value/ 1549560720 / inspected 7-Feb-2019 /
],
[
/salt/ h'7ed13a094d0effbf257f5522fdb87446',
/value/ 1612498440 / inspected 4-Feb-2021 /
],
[
/salt/ h'd006ff82a4d84bcade7a008ad0fadb6e',
/value/ 1674004740 / inspected 17-Jan-2023 /
],
[
/salt/ h'ff65d029bca807f1fcd7fc7a66223ae1'
],
[
/salt/ h'c7ecad77d36b5b171573d2e32d650a1e'
]
]>>,
/ inspection_location /
<<[
[
/salt/ h'e39612407e99a347d61442957b3dfdac',
/value/ "us",
/claim/ "country"
],
[
/salt/ h'4569990258b25a5267c17a3e3a225ec3',
/value/ "ca",
/claim/ "region"
],
[
/salt/ h'e27403129cd88bf8fee4193e65339a35'
]
]>>
]
},
/ CWT payload / << {
/ iss / 1 : "https://issuer.example",
/ sub / 2 : "https://holder.example",
/ exp / 4 : 1725330600, /2024-09-03T02:30:00+00:00Z/
/ nbf / 5 : 1725243900, /2024-09-02T02:25:00+00:00Z/
/ iat / 6 : 1725244200, /2024-09-02T02:30:00+00:00Z/
/ cnf / 8 : {
/ cose key / 1 : {
/ kty / 1: 2, / EC2 /
/ crv / -1: 1, / P-256 /
/ x / -2: h'8554eb275dcd6fbd1c7ac641aa2c90d9
2022fd0d3024b5af18c7cc61ad527a2d',
/ y / -3: h'4dc7ae2c677e96d0cc82597655ce92d5
503f54293d87875d1e79ce4770194343'
}
},
"most_recent_inspection_passed": true,
"inspection_dates": [
/ redacted_element_hash of all inspection dates /
89([3, h'a9e2b659695a7af97fcf25f8e833ffa2
0a4316fe29644715bdbd3804ac2bed99'])
],
"inspection_location": {
"postal_code": "94188",
/ redacted_claim_hash of country and region /
simple(60) : [2, h'02d992604bf0618156a8f5eef336f676
1db9af99edbc662e7c32850557a0ebd9']
},
/ redacted_claim_hash of inspector_license_number /
simple(60) : [3, h'3641ce21bec3c8c109da92b0be662719
b67cd8a99e99cd3b379c1ff466c0ec28']
} >>,
/ CWT signature / h'dc15ca869bad13b9a827191d7d71a444
7ff213168f401982009a1c3629bce4a5
921642d9f15707541fdc7d9bad5d37b6
5d4d779b72273b9d1776a6675920a1a2
68272dc848858b9ccdfc45521bbb3247
316db1b829b63d63198af2b608826768'
])
An SMD-CWT MUST declare its content type by including the typ protected header parameter [RFC9596] with one of the
following values:¶
A Holder can selectively present some of the previously redacted claims in an SMD-KBT. An SMD-KBT has the same structure as an SD-KBT. The only difference is that, rather than simply omitting the Disclosures it does not wish to reveal, the Holder transforms each Disclosure introduced by this document from a simple enumeration of values into a Disclosure Proof: an array containing one Merkle proof per presented leaf.¶
The Merkle proofs of a Disclosure Proof are not independent of each other. The hash of a copath node is not included in a Merkle proof when its subtree contains a presented leaf, since the Verifier recomputes it, or when it is already included in the Merkle proof of a previous leaf.¶
For a given Disclosure, the Holder proceeds as follows:¶
Iterate over the non-Decoy entries and select those to be presented. In the example of Figure 11,
leaves A to E are iterated over, and only A, D, and E are presented.¶
Initialize a visited set with the node indexes of the selected leaves and of all their ancestors. In the example of
Figure 11, the visited set contains nodes 0, 6, and 8 (A, D, and E) and nodes 1, 3, 5, 7, 9,
and 11 (J, R, K, V, L, and S).¶
For each selected leaf, from left to right, build its Merkle proof as an array:¶
Build a Redacted Entry by prefixing the SMD-CWT entry with the node index of the leaf, and place it as the first element of the Merkle proof.¶
Walk the copath of that leaf, from the leaf up to the root. For each node of the copath:¶
If this node is in the visited set, skip it.¶
Otherwise, append the hash of that node to the Merkle proof and add the node to the visited set. If that
node is a leaf, its hash is the hash of its entry, computed as described in Section 4.3.
Otherwise, its hash is the MTH of the subtree rooted at that node.¶
The Disclosure Proof is the array of the Merkle proofs, ordered by increasing node index of their leaf.¶
In the following examples, hash<<X>> denotes the hash of the entry X when X is a leaf, and the MTH of the
subtree rooted at X otherwise.¶
The copath of A consists of nodes 2 (B), 5 (K), and 11 (S). B is not visited: its hash is appended. K and
S are visited: they are skipped. The Merkle proof for A is therefore:¶
[ [0, h'4e2f040d5bb57daf86698066be470c24', "A"], hash<<B>>, ]
The copath of D consists of nodes 4 (C), 1 (J), and 11 (S). C is not visited: its hash is appended. J and
S are visited: they are skipped. The Merkle proof for D is therefore:¶
[ [6, h'add7fe2b052af5faf0ec67f57eb1454f', "D"], hash<<C>>, ]
The copath of E consists of nodes 10 (d1), 13 (M), and 3 (R). d1 and M are not visited: their hashes are
appended. R is visited: it is skipped. The Merkle proof for E is therefore:¶
[ [8, h'6e0e0494c6aa9f9072c3410304aab730', "E"], hash<<d1>>, hash<<M>>, ]
The resulting Disclosure Proof is shown in Figure 15. It contains 4 hashes. The hashes of J, K, R,
L, S, and V are recomputed by the Verifier.¶
[ [ [0, h'4e2f040d5bb57daf86698066be470c24', "A"], hash<<B>> ], / "A" / [ [6, h'add7fe2b052af5faf0ec67f57eb1454f', "D"], hash<<C>> ], / "D" / [ [8, h'6e0e0494c6aa9f9072c3410304aab730', "E"], hash<<d1>>, hash<<M>> ] / "E" / ]
If the Holder presents all the non-Decoy entries A to E of Figure 11 instead, every copath node of
A, B, C, and D is visited: their Merkle proofs each contain only their Redacted Entry. The Merkle proof of
E is unchanged and contains hash<<d1>> and hash<<M>>. The resulting Disclosure Proof contains 2 hashes.¶
If the Holder presents only A and B, the Merkle proof of A contains hash<<K>> and hash<<S>>, which are then
visited, so the Merkle proof of B contains no hash.¶
An SMD-CWT Verifier MUST perform the same verification as an SD-CWT Verifier. This section only describes how to
validate a Disclosure Proof against the redacted_root_hash of the corresponding container.¶
To validate an SMD-KBT, repeat this verification for all the disclosures presented. Then also perform the validation described in Section 9 of [SD-CWT] since they all should pass as well.¶
In this section, n is the size encoded in the redacted_root_hash (the first element of the array); the Merkle tree
therefore has 2^n leaves, its node indexes range from 0 to 2^ (n+1) - 2, and its root has node index 2^n - 1.¶
The Verifier proceeds as follows:¶
Verify that the Disclosure Proof contains at least one and at most 2^n Merkle proofs.¶
For each Merkle proof:¶
Verify that it contains at most n + 1 elements.¶
Verify that its first element is a Redacted Entry, and that the node index of this Redacted Entry is the node index of a leaf, i.e., an even number less than or equal to 2^ (n+1) - 2.¶
Verify that this Redacted Entry matches the type of the container: a salted-merkle-claim if the container
is a map, or a salted-merkle-element if it is an array, as defined in Figure 9. In
particular, a Redacted Entry of a Decoy, which only contains a salt, is rejected.¶
Verify that the node indexes of the Redacted Entries are sorted in increasing order.¶
Initialize a visited set with the node indexes of the presented leaves and of all their ancestors. Also maintain a table associating node indexes with hashes, initially empty.¶
For each Merkle proof:¶
Remove the node index from the Redacted Entry. The remaining array is an SMD-CWT entry: compute its hash as described in Section 4.3 and record it for the leaf in the table.¶
Walk the copath of the leaf, from the leaf up to the root. For each node of the copath:¶
Verify that all the hashes of the Merkle proof have been consumed. If not, the validation fails.¶
Compute the hash of the root by walking down the tree from the root. For each node reached:¶
If the table records a hash for this node, this is its hash, and its subtree is not walked.¶
Otherwise, if this node is a leaf, the validation fails.¶
Otherwise, walk its left child and then its right child. Its hash is the hash of the concatenation of their hashes, the hash of the left child coming first.¶
Verify that the hash of the root is equal to the root hash in the redacted_root_hash.¶
If any of these verifications fails, the validation of the whole Disclosure Proof fails.¶
Applied to the Disclosure Proof of Figure 15, the visited set initially contains nodes 0, 1, 3, 5, 6, 7, 8, 9, and 11. The Verifier then:¶
Processes the Merkle proof of A: it records hash<<A>> for node 0 and hash<<B>> for node 2. Nodes 5 and 11
are visited.¶
Processes the Merkle proof of D: it records hash<<D>> for node 6 and hash<<C>> for node 4. Nodes 1 and 11 are
visited.¶
Processes the Merkle proof of E: it records hash<<E>> for node 8, hash<<d1>> for node 10, and hash<<M>> for
node 13. Node 3 is visited.¶
Computes the hash of the root. The visited set now contains nodes 0 to 11 and 13, and the table associates nodes with
hashes [(0, A), (2, B), (4, C), (6, D), (8, E), (10, d1), (13, M)]. The root V (node 7) is not in the
table, so the Verifier walks down to R (node 3) and S (node 11), which are not in the table either. Under R,
J (node 1) and K (node 5) are computed from nodes 0 and 2, and 4 and 6. Under S, L (node 9) is computed from
nodes 8 and 10, and M (node 13) is in the table. R is then computed from J and K, S from L and M, and
V from R and S.¶
Verifies that hash<<V>> is equal to the root hash in the redacted_root_hash.¶
In SD-CWT, the payload contains the hash of every redacted entry, disclosed or not: a container with e redacted
entries
costs 34 * e bytes in every presentation (assuming sd_alg is SHA-256).¶
The size of a presentation therefore grows linearly with e in SD-CWT, but only logarithmically in SMD-CWT. For instance, the Disclosure Proof of Figure 15 contains 4 hashes in addition to the root hash, i.e., 34 * 5 = 170 bytes, whereas an SD-CWT with the same 5 entries and 2 Decoys contains 34 * 7 = 238 bytes of hashes.¶
In SD-CWT, the payload contains one hash per redacted entry, so a Verifier learns the number of redacted entries of each container Also given presentation of SD-KBT are linkable, a Verifier can witness an array of redacted elements grow or shrink which degrades privacy of the Holder. Decoys can be used to mitigate that, but they are expensive in terms of space wasted.¶
In SMD-CWT, the Verifier only learns the logarithmic size of the tree. The Issuer can choose a larger n to hide this number further, at the cost of at most one hash per additional level (see Section 7.3).¶
In SD-CWT, each Decoy adds one hash, i.e., 34 bytes, to the presented token.¶
In SMD-CWT, the presented token contains only the root hash and the Merkle proofs of the disclosed claims. The size of these proofs depends on the height of the tree, not on the number of its leaves. Decoys can therefore be added at no cost up to the next power of two. Beyond that, doubling the number of leaves adds one level to the tree, which costs at most one additional hash, i.e., 34 bytes: the subtree rooted at the new copath node contains no presented leaf, and its hash is included at most once in the Disclosure Proof (see Section 5).¶
TODO: The sparser the presentation, the faster the verification; however, a full presentation takes twice as long to verify.¶
TODO Security¶
IANA is requested to register the following media types in the "Media Types" registry:¶
The following completed registration template is provided:¶
Type name: application¶
Subtype name: smd-cwt¶
Required parameters: n/a¶
Optional parameters: n/a¶
Encoding considerations: binary¶
Security considerations: Section 9 of this specification and [RFC8392]¶
Interoperability considerations: n/a¶
Applications that use this media type: TBD¶
Fragment identifier considerations: n/a¶
Additional information:¶
Person & email address to contact for further information: SPICE WG mailing list (spice@ietf.org) or IETF Security Area (saag@ietf.org)¶
Intended usage: COMMON¶
Restrictions on usage: none¶
Author: See Author's Addresses section¶
Change controller: IETF¶
Provisional registration? No¶
The following completed registration template is provided:¶
Type name: application¶
Subtype name: smd-kbt¶
Required parameters: n/a¶
Optional parameters: n/a¶
Encoding considerations: binary¶
Security considerations: Section 9 of this specification and [RFC8392]¶
Interoperability considerations: n/a¶
Applications that use this media type: TBD¶
Fragment identifier considerations: n/a¶
Additional information:¶
Person & email address to contact for further information: SPICE WG mailing list (spice@ietf.org) or IETF Security Area (saag@ietf.org)¶
Intended usage: COMMON¶
Restrictions on usage: none¶
Author: See Author's Addresses section¶
Change controller: IETF¶
Provisional registration? No¶
; in SMD-CWT
salted-merkle-array = [ +bstr-encoded-salted-merkle-entry ]
bstr-encoded-salted-merkle-entry = bstr .cbor salted-merkle-entries
; in SMD-KBT
salted-array-proofs = [ +bstr-encoded-salted-proof ]
bstr-encoded-salted-proof = bstr .cbor disclosure-proof
; where salted-claim, salted-element and decoy are already defined in {{SD-CWT}}
salted-merkle-entry = salted-claim / salted-element / decoy
salted-merkle-entries = [ +salted-merkle-entry ]
; one Merkle proof per presented leaf, ordered by increasing node index
disclosure-proof = [ +merkle-proof ]
merkle-proof = [
redacted-entry,
* bstr ; hash of a copath node, from the leaf up to the root
]
; a presented entry prefixed with the node index of its leaf; Decoys are never presented
redacted-entry = salted-merkle-claim / salted-merkle-element
salted-merkle-claim = [
uint, ; node index of the leaf
bstr .size 16, ; 128-bit salt
any, ; Claim Value
(int / text) ; Claim Key
]
salted-merkle-element = [
uint, ; node index of the leaf
bstr .size 16, ; 128-bit salt
any ; Claim Value
]
; repeated here
salted-claim = [
bstr .size 16, ; 128-bit salt
any, ; Claim Value
(int / text) ; Claim Key
]
salted-element = [
bstr .size 16, ; 128-bit salt
any ; Claim Value
]
decoy = [
bstr .size 16 ; 128-bit salt
]
; redacted_claims_root is used as a map label. The corresponding value is
; a Redacted Claim Root Hash.
; TODO: any Unassigned value in https://www.iana.org/assignments/cbor-simple-values#simple
redacted_claims_hash = #7.60 ; CBOR simple value 60
redacted_root_hash = [
uint ; logarithm(2) of the number of leaves represented in this root hash
bstr, ; root hash
]
; CBOR tag for wrapping the Merkle Root Hash of all the redacted elements in an array.
; TODO: any Unassigned in https://www.iana.org/assignments/cbor-tags#tags
MERKLE_REDACTED_ELEMENT_TAGNUM = 89
; redacted_elements_root is used in CDDL payloads that contain
; array elements that are redacted.
redacted_element_hash = #6.<MERKLE_REDACTED_ELEMENT_TAGNUM>( redacted_root_hash )
TODO acknowledge.¶