pub struct IvStash { /* private fields */ }Expand description
Remembers the IV used for each (type, plaintext, aad) triple so re-encrypting
an unchanged value reproduces its exact previous ciphertext.
This is not an optimisation. sops edit decrypts, hands the tree to an
editor, and re-encrypts everything; without the stash every line of the
file changes on every edit, which destroys the property the whole format
exists for — a readable, reviewable diff.
§The type is part of the key, and leaving it out is a real bug
Upstream’s key is stashKey{plaintext interface{}, additionalData string}, and
a Go map compares an interface{} by dynamic type and value — so int(1)
and string("1") are two different keys there. The first version of this
struct keyed on the raw plaintext bytes, which collapses exactly the pairs
the encodings make indistinguishable:
| these are distinct upstream | but share one byte string |
|---|---|
1 (int) / 1.0 (float) / "1" (str) | 1 |
true (bool) / "True" (str) | True |
false (bool) / "False" (str) | False |
Two such leaves under the same AAD — which is to say two elements of one
list, since a sequence adds no path component — would then be handed the same
nonce. The plaintext bytes are equal, so this is not the catastrophic form of
GCM nonce reuse; the consequence is a file whose bytes differ from the one
sops would have written, which for a tool whose entire claim is byte-parity is
the bug that matters. LeafType is in the key.
§The reuse that remains, stated rather than inherited
Two genuinely identical typed values at one path do still share a nonce. The plaintexts are identical, so an attacker learns only that they are equal — which any deterministic encryption concedes by construction. It is a knowing trade, confined to unchanged values, and it is the price of a reviewable diff.
Implementations§
Source§impl IvStash
impl IvStash
pub fn new() -> Self
Sourcepub fn remember(&mut self, plaintext: &Plaintext, aad: &Aad, iv: &[u8])
pub fn remember(&mut self, plaintext: &Plaintext, aad: &Aad, iv: &[u8])
Record the IV a leaf was decrypted with, so an unchanged value keeps it.
Sourcepub fn recall(&self, plaintext: &Plaintext, aad: &Aad) -> Option<Iv>
pub fn recall(&self, plaintext: &Plaintext, aad: &Aad) -> Option<Iv>
The remembered IV for this pair, if any.