[noise] Symmetric-crypto overhaul and stateful hashing

Paul Rösler paul.roesler at rub.de
Tue Nov 13 02:28:02 PST 2018


Hi Trevor,

> Date: Mon, 12 Nov 2018 08:06:53 +0000
> From: Trevor Perrin <trevp at trevp.net>
> Anyways, below is a proposal for a "symmetric crypto overhaul"
> centered on changing our API to the cryptographic hash so we expect a
> "stateful hashing object", instead of just a HASH() function.
> 
> Given such an object, we can define our symmetric crypto using
> Sponge/STROBE-inspired "absorb" / "squeeze" / "ratchet" / "clone"
> operations.  I think this would remove some small awkwardness and
> inefficiency in our current design.
> 
> Definitely would appreciate feedback and review, this would be a major
> change (though it would just be new HASH options in the Noise protocol
> name, we wouldn't break compatibility).
In general I really like the idea. When we were looking at Noise from a
theoretical point of view, we were trying to extract generic building
blocks (with own functionality and security definitions) that are used
similarly in all patterns but are more generic than DH, Enc, H, ... .
One of these was definitely the hashing. However, due to the interleave
of the single building blocks, we were not quite able to do so.

My comments below are rather from my cryptographic view than from a
developer's.

> Goals for symmetric-key overhaul:
> -----------------------------------
>  * Replace ck and h variables with a single hash state which all
> inputs are hashed into, for simplicity and efficiency.
>  * Allow non-HKDF/HMAC options, for simplicity and efficiency.
>  * Allow packing of separate inputs into a single hash block, for efficiency.
All of them totally make sense.

>  * Provide simpler hashing, so that Noise keys can be derived directly
> as key = hash(inputs), without long sequences of nested hashing.
I guess this refers to the API? Because otherwise we have two different
primitives (one stateful, one stateless). If it refers to API, then I agree.

>  * Allow for Sponge/STROBE-like algorithms where the hash object is
> capable of "Duplex"-style encryption/decryption, so implementations
> can minimize code size by using a single crypto primitive like Keccak.
I'm like the idea of generalizing and combining compatible building
blocks into a more abstract primitive. However, mixing more independent
functionality into a primitive makes it complicated to define and
understand security. As a secure key computation can always be composed
with a secure cipher, I do not see the reason for putting both into one
primitive (at least from a theoretical point of view).

>  * Decouple "squeezing" outputs from "absorbing" inputs to make it
> easier to output Additional Symmetric Keys.
I totally agree since these two operations are distinct with respect to
the functionality of this "stateful"-hash primitive.

>  * Decouple "absorbing" from "ratcheting" so we can absorb inputs more
> efficiently and only "ratchet" when needed for forward-secrecy.
Sounds legit, however I am not sure whether this is understood well by
all developers. So in order to prevent squeezing without ratcheting
(i.e., one squeezes without using the new absorbed entropy), the API
should take care of this (e.g., by always ratcheting if something was
absorbed recently, but ratcheting was not actively invoked).

>  * Provide an abstract API to the underlying stateful hash which can
> be implemented via traditional hashes (with or without HMAC/HKDF), as
> well as STROBE or other sponge constructions.
Totally agree.

> Notes:
> 
>  * Noise will never squeeze more than HASHLEN bytes of output, for
> compatibility with traditional hashes.
As you are aiming for a generic primitive, why should the squeeze
operation not require its (hash-based) implementation to generate as
much output as requested (e.g., by iteratively ratcheting and squeezing)?

>  * Noise will assume that outputs from Squeeze or Encrypt/Decrypt
> depend on a transcript containing all previous arguments to Absorb
> calls.
Sure.

>  * However, Noise does NOT assume that this transcript contains the
> length/type of previous inputs.  So Noise will encode this information
> itself in Absorb inputs (which allows slightly more efficient stateful
> hash implementations compared to something like STROBE, since Noise
> can omit type/length information in many cases).
I agree, absorbing should only take the input as raw data.

>  * The Encrypt/Decrypt operations will be possessed by some crypto
> objects (like STROBE or other Sponge/Duplex objects).  In this case we
> don't have to derive a key from the object and use it with an AEAD, we
> can just ask the object to encrypt/decrypt things directly.
As written above, I do not see why this should be combined.

Due my comments for now, I do not go deeper into the example. As written
above, I totally support that the way hashes are computed can be
understood as a stateful "sponge". However, from my point of view, a
combination of a stateful sponge and a cipher seems unnatural. If its'
idea is further extended to an updatable channel, then this may make
sense again (but that would be independent of hashing).

Cheers,
Paul

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: OpenPGP digital signature
URL: <http://moderncrypto.org/mail-archive/noise/attachments/20181113/d6bef6de/attachment.sig>


More information about the Noise mailing list