[noise] Symmetric-crypto overhaul and stateful hashing

Trevor Perrin trevp at trevp.net
Mon Nov 12 03:50:35 PST 2018


On Mon, Nov 12, 2018 at 8:06 AM Trevor Perrin <trevp at trevp.net> wrote:
>
> MixHash() would be split into fixed-length and variable-length
> versions, so we can pack inputs into hash blocks efficiently (omitting
> length fields for fixed-length values).  Length fields are added after
> inputs to support streaming, using right-parseable "byte-reversed
> varints" for efficiency.

Mistake already!

For any Squeeze() output, the transcript needs to be parseable from
the right to determine the type of output ("k", "h, "i", "r", "a").
Then the remainder of the transcript needs to be parseable from the
left to determine at what point in the transcript this output was
produced.

So variable-length fields need the length prepended for left-parsing,
and appended for right-parsing.  At the moment the right-parsing only
affects the ASK label (and not ratcheting, as I incorrectly stated,
since ratcheting just has to zero-pad to the next hash block boundary,
thus it can be left-parsed unambiguously).

An alternative design would be to hash a type byte (and maybe length
field) before every input, so the transcript could branch at any point
and be left-parseable.  But I don't think we need that flexibility, so
this way seems more efficient and simple.


MixHashVariableLen(x):
  Absorb(len(x) || x)  // len: varint

MixHashVariableLenRight(x):
  Absorb(x || reverse_len(x))  // len: byte-reversed varint
...

transcript = len(name) || name || len(prologue) || prologue || e || es
k1 = HASH(transcript || "k")

transcript = transcript || s || ss
k2 = HASH(transcript || "k")
k3 = HASH(transcript || "i")

transcript = transcript || len(payload_ciphertext) || payload_ciphertext
h  = HASH(transcript || "h")
ask = HASH(transcript || label || reverse_len(label) || "a")

Trevor


More information about the Noise mailing list