Skip to content

Commit e979b21

Browse files
committed
Add BCR-2026-004: Envelope Salted Values
1 parent ec99270 commit e979b21

2 files changed

Lines changed: 355 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ Each BCR has a status which is indicated by a symbol.
8888
| [BCR-2025-006](papers/bcr-2025-006-hubert.md) | Hubert: Distributed Key-Value Store for Secure Multiparty Coordination | Wolf McNally | ⭐️ |
8989
| [BCR-2026-001](papers/bcr-2026-001-unit.md) | Unit: The Known Value for Deliberate Emptiness | Wolf McNally | ⭐️ |
9090
| [BCR-2026-002](papers/bcr-2026-002-envelope-notation.md) | Gordian Envelope Notation - Quick Reference | Wolf McNally | ⭐️ |
91-
| [BCR-2026-003](papers/bcr-2026-003-xid-edges.md) | XID Edges: Verifiable Claims Between Entities | Wolf McNally | 📙 |
91+
| [BCR-2026-003](papers/bcr-2026-003-xid-edges.md) | XID Edges: Verifiable Claims Between Entities | Wolf McNally | ⭐️ |
92+
| [BCR-2026-004](papers/bcr-2026-004-salted-value.md) | Envelope Salted Values | Wolf McNally | 📙 |
9293

9394
_Also see our [Testimony](https://github.com/BlockchainCommons/Testimony/blob/master/README.md) and our [Blockchain Commons Proposals](https://github.com/BlockchainCommons/bcps/blob/master/README.md)._
9495

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
# Envelope Salted Values
2+
3+
This document defines a standard **Salted Value** pattern for Gordian Envelope, enabling optional decorrelation of small or easily enumerable values that may be elided.
4+
5+
## BCR-2026-004
6+
7+
**© 2026 Blockchain Commons**
8+
9+
Authors: Wolf McNally, Christopher Allen<br/>
10+
Date: February 4, 2026
11+
12+
---
13+
14+
## Abstract
15+
16+
Gordian Envelope supports *holder-based elision*: selectively withholding parts of an envelope while preserving verification through the digest tree. However, elided elements are replaced by their digests, and **digests are correlatable**: repeated elisions of the same underlying value yield identical digests, enabling cross-presentation linkage and (for small value spaces) dictionary attacks.
17+
18+
[BCR-2024-007](bcr-2024-007-envelope-decorrelation.md) introduces opt-in decorrelation in Gordian Envelope using `'salt': Salt` assertions. This document defines a **Salted Value** pattern—an Envelope-native wrapper that standardizes how to salt “atomic” values (strings, small enums, etc.) while keeping them readable when disclosed.
19+
20+
A value MAY be represented directly (unsalted):
21+
22+
```envelope
23+
"Indiana"
24+
```
25+
26+
Or as a Salted Value using **Unit** as subject:
27+
28+
```envelope
29+
'' [
30+
'salt': Salt(<random-data>)
31+
'value': "Indiana"
32+
]
33+
```
34+
35+
This document also explains how envelope schemas may define assertions as:
36+
37+
- optionally accepting Salted Values,
38+
- requiring Salted Values, or
39+
- forbidding Salted Values,
40+
41+
depending on privacy needs, future elision expectations, and determinism requirements.
42+
43+
---
44+
45+
## Status of This Document
46+
47+
📙 This document is research and a proposed specification. It defines a reusable pattern intended for broad application across Envelope schemas, but it does not yet have a reference implementation.
48+
49+
---
50+
51+
## Background
52+
53+
### Unit and record-like values
54+
55+
[BCR-2026-001](bcr-2026-001-unit.md) defines **Unit** (`''`, Known Value 0) as deliberate emptiness: a position that carries zero informational content and must not be replaced with any other value. In Gordian Envelope, Unit is used as the subject when an envelope’s meaning is conveyed entirely by its assertions, without implying a subject identity.
56+
57+
Salted Values are *record-like wrappers*: they exist to carry assertions (`'salt'` and `'value'`). They are not independently-identified entities. Therefore, Salted Values use **Unit** as their subject.
58+
59+
### Salt
60+
61+
[BCR-2023-017](bcr-2023-017-salt.md) defines `salt` as random bytes used as an additional input to one-way algorithms where similar inputs should not yield the same outputs (“decorrelation”). Salts are not usually secret.
62+
63+
In Envelope, salt is carried as a `Salt` object with CBOR tag `#6.40018(bytes)`.
64+
65+
### Decorrelation and elision
66+
67+
[BCR-2024-007](bcr-2024-007-envelope-decorrelation.md) explains correlatability in the context of Envelope’s Merkle-like digest tree:
68+
69+
- When an element is elided, it is replaced with its digest, preserving the digest tree.
70+
- Digests are correlatable: identical hidden values produce identical digests.
71+
- Envelope supports opt-in decorrelation by adding `'salt': Salt` assertions at the correct level (subject, object, or assertion) to ensure elided digests do not correlate.
72+
73+
This BCR defines a standard wrapper that makes it easy for schemas to say: “this value may be salted in a consistent way.”
74+
75+
---
76+
77+
## Motivation
78+
79+
Many real-world fields are drawn from **small or enumerable sets**, and are often **privacy-sensitive** when withheld:
80+
81+
- US state codes (`"ID"`, `"CA"`, ...)
82+
- cities/towns (often enumerable within a jurisdiction)
83+
- standardized roles (`"Release Manager"`, `"Witness"`)
84+
- categorical labels used in workflows
85+
86+
If such values are elided without decorrelation, their digests can be:
87+
88+
1. **Linked** across different presentations (correlation), and/or
89+
2. **Recovered** via dictionary attack if the value space is small.
90+
91+
The Salted Value pattern provides a simple, schema-friendly way to represent these values so that if the *entire value object* is elided, its resulting digest is decorrelated.
92+
93+
---
94+
95+
## The Salted Value Pattern
96+
97+
### Definitions
98+
99+
A **Salted Value** is an envelope with:
100+
101+
- subject: **Unit** (`''`)
102+
- required assertions:
103+
- `'salt': Salt(...)`
104+
- `'value': <any value>`
105+
106+
A Salted Value is semantically equivalent (for interpretation) to its underlying `'value'`, except that it carries a salt that changes its digest for decorrelation purposes.
107+
108+
### Representation
109+
110+
#### Unsalted value
111+
112+
Any ordinary Envelope value:
113+
114+
```envelope
115+
"Indiana"
116+
```
117+
118+
#### Salted value
119+
120+
A Salted Value wrapper:
121+
122+
```envelope
123+
'' [
124+
'salt': Salt(<random-data>)
125+
'value': "Indiana"
126+
]
127+
```
128+
129+
### Required predicates
130+
131+
- `'salt'` is an existing Known Value (see [BCR-2024-007](bcr-2024-007-envelope-decorrelation.md)).
132+
- `'value'` is a proposed new Known Value (code point TBD) representing the wrapped underlying value.
133+
134+
Pattern invariants:
135+
136+
- The subject MUST be Unit (`''`) per [BCR-2026-001](bcr-2026-001-unit.md).
137+
- There MUST be exactly one `'salt'` assertion, and its object must be a `Salt` of at least 8 bytes (see below for further guidance),
138+
- There MUST be exactly one `'value'` assertion, and its object may be anything.
139+
- There MUST NOT be any other assertions.
140+
141+
---
142+
143+
## How Salted Values Provide Decorrelation
144+
145+
A Salted Value is itself an envelope element. Because it contains a `'salt': Salt(...)` assertion, its digest is altered by random data. If the Salted Value is elided as an *object* in some larger envelope, the resulting digest is decorrelated.
146+
147+
Example (field value is salted):
148+
149+
```envelope
150+
'region': '' [
151+
'salt': Salt(<random-data>)
152+
'value': "CA"
153+
]
154+
```
155+
156+
If the holder later elides the entire object:
157+
158+
```envelope
159+
'region': ELIDED
160+
```
161+
162+
…the digest standing in for the elided object is now a digest of the **salted wrapper**, not of `"CA"` directly. This prevents correlation and makes dictionary attacks impractical (absent disclosure of the wrapper).
163+
164+
### Important disclosure guidance
165+
166+
If concealment is the goal, presentations SHOULD elide the **entire Salted Value object**, not merely the `'value'` assertion inside it.
167+
168+
Revealing the wrapper while eliding only `'value'`:
169+
170+
```envelope
171+
'' [
172+
'salt': Salt(<random-data>)
173+
'value': ELIDED
174+
]
175+
```
176+
177+
…can leak enough structure to enable brute-force recovery in small value spaces (because the elided leaf digest corresponds to the underlying value). For small enumerated fields, that defeats the purpose.
178+
179+
One *can* disclose the `'value`' without disclosing the `'salt'`, although this provides little additional security benefit:
180+
181+
```envelope
182+
'' [
183+
'salt': ELIDED
184+
'value': "CA"
185+
]
186+
```
187+
188+
**Rule of thumb:**
189+
190+
- To *reveal* the value: disclose the wrapper (or disclose the unsalted value, if allowed).
191+
- To *conceal* the value: elide the wrapper object entirely.
192+
193+
---
194+
195+
## Salt Selection Guidance
196+
197+
[BCR-2024-007](bcr-2024-007-envelope-decorrelation.md) recommends salt sizes chosen to minimize correlation and quasicorrelation:
198+
199+
- For small objects, salt is generally 8…16 bytes.
200+
- For larger objects, salt is generally 5%…25% of object size.
201+
202+
For Salted Values (which are commonly used for small strings/enums), producers SHOULD use random salts in the **8…16 byte** range, and MAY choose a random length within that range to reduce size-based leakage.
203+
204+
Salts MUST be random (see [BCR-2023-017](bcr-2023-017-salt.md)).
205+
206+
Salts SHOULD be added during envelope construction *before* applying any signatures that depend on the digest tree (see [BCR-2024-007](bcr-2024-007-envelope-decorrelation.md)).
207+
208+
---
209+
210+
## Schema Integration
211+
212+
Salted Values are most useful when schemas explicitly support them, so that producers and verifiers share expectations.
213+
214+
A schema may treat a field as:
215+
216+
1. **Optionally salted** (accept either form)
217+
2. **Required salted** (always use the Salted Value wrapper)
218+
3. **Forbidden salted** (the default: only accept the direct/unsalted form)
219+
220+
### Optionally salted
221+
222+
A schema MAY define a field as accepting either:
223+
224+
- the direct value, or
225+
- a Salted Value wrapping that value
226+
227+
Example schema intent:
228+
229+
- `region` may be `"CA"` or `''['salt':..., 'value':"CA"]`
230+
231+
This choice is appropriate when:
232+
233+
- the field is usually disclosed, but
234+
- the field might later be selectively withheld, and
235+
- producers want the option to pre-commit in a decorrelatable way.
236+
237+
**Reasonable use case:** a location object where region/locality are usually present, but may be withheld in some presentations for privacy.
238+
239+
### Required salted
240+
241+
A schema MAY require that a field always be represented as a Salted Value wrapper.
242+
243+
This choice is appropriate when:
244+
245+
- the value space is small and correlation/dictionary attacks are a concern, and
246+
- withholding is expected or common, and
247+
- determinism (same inputs → same digests) is not required for that field.
248+
249+
**Reasonable use case:** `locality`, `role`, or other fields that are frequently elided and have high correlation risk.
250+
251+
### Forbidden salted
252+
253+
A schema MAY forbid Salted Value wrappers for fields that must remain deterministic or directly comparable at the digest level.
254+
255+
This choice is appropriate when:
256+
257+
- the field participates in canonical identifiers, keys, indexes, or deterministic commitments, or
258+
- correlation is desired (e.g., you want equal values to be obviously equal across envelopes), or
259+
- the field is always public and never elided.
260+
261+
**Reasonable use case:** fields intended as stable identifiers, fixed policy URIs, or other values where non-determinism would be harmful.
262+
263+
Where a schema is silent on whether Salted Values are allowed, the default is to forbid them.
264+
265+
---
266+
267+
## Examples
268+
269+
### Example 1: Optional salted region
270+
271+
Unsalted:
272+
273+
```envelope
274+
'region': "CA"
275+
```
276+
277+
Salted:
278+
279+
```envelope
280+
'region': '' [
281+
'salt': Salt(<random-data>)
282+
'value': "CA"
283+
]
284+
```
285+
286+
### Example 2: Required salted locality
287+
288+
Schema requires locality to be salted because it may be elided and is easily enumerable:
289+
290+
```envelope
291+
'locality': '' [
292+
'salt': Salt(<random-data>)
293+
'value': "Sacramento"
294+
]
295+
```
296+
297+
Concealed presentation:
298+
299+
```envelope
300+
'locality': ELIDED
301+
```
302+
303+
### Example 3: Combining with higher-level structures
304+
305+
A place object that supports optional salted small fields:
306+
307+
```envelope
308+
'' [
309+
'country': "US"
310+
'region': '' [
311+
'salt': Salt(<random-data>)
312+
'value': "CA"
313+
]
314+
'locality': '' [
315+
'salt': Salt(<random-data>)
316+
'value': "Sacramento"
317+
]
318+
'timeZone': "America/Los_Angeles"
319+
]
320+
```
321+
322+
---
323+
324+
## Security Considerations
325+
326+
1. **Salt is not secrecy.** Salt is not usually secret; its purpose is decorrelation of projections, not encryption (see [BCR-2023-017](bcr-2023-017-salt.md)).
327+
2. **Elide at the right level.** To conceal a value while benefiting from decorrelation, elide the Salted Value object as a whole. Revealing the wrapper while eliding only `'value'` can enable dictionary attacks in small value spaces.
328+
3. **Non-determinism is intentional.** Salted Values break deterministic equality-at-the-digest-level. Schemas should forbid Salted Values where determinism is required.
329+
4. **Add salt before signing.** Because salts change the digest tree, they must be part of the envelope before signatures that commit to those digests (see [BCR-2024-007](bcr-2024-007-envelope-decorrelation.md)).
330+
5. **Fresh salt per value.** Reusing the same salt (or copying an entire Salted Value wrapper) across contexts reintroduces correlatability. Salts should be freshly generated per wrapped value.
331+
6. **Eliding a parent node inherits its child salts.** When a parent node with salted children is elided, the parent MAY be considered effectively salted as well, as the child salt(s) also serve to decorrelate the parent.
332+
333+
---
334+
335+
## Future Work
336+
337+
- Define schema notation patterns (human- and machine-readable) for expressing “optional salted” vs “required salted” field constraints.
338+
339+
---
340+
341+
## References
342+
343+
### Internal (BCR)
344+
345+
- [BCR-2026-001: Unit: The Known Value for Deliberate Emptiness](bcr-2026-001-unit.md)
346+
- [BCR-2023-017: UR Type Definition for Random Salt](bcr-2023-017-salt.md)
347+
- [BCR-2024-007: Decorrelation in Gordian Envelope](bcr-2024-007-envelope-decorrelation.md)
348+
- [BCR-2023-002: Known Values](bcr-2023-002-known-value.md)
349+
- [BCR-2024-009: Signatures with Metadata in Gordian Envelope](bcr-2024-009-signature-metadata.md)
350+
351+
### External
352+
353+
- https://en.wikipedia.org/wiki/Salt_(cryptography) (background concept; Envelope use is defined by the BCRs above)

0 commit comments

Comments
 (0)