[noise] NXOF?
Trevor Perrin
trevp at trevp.net
Sat Mar 3 18:44:54 PST 2018
Here's a cleaned-up version of the NXOF idea, including a question for
cryptographers at the end:
Definitions
------------
An NXOF is a stateful object with one method:
- Hash(input, len)
- returns byte-sequence of length len
Two functions are used for creating NXOFs:
- RootHash(protocolname, len)
- returns bytes that can be used to create a new NXOF
- CreateNXOF(bytes[1..HASHLEN])
- returns a new NXOF
- must be called with a HASHLEN-length byte sequence taken from
the output of Hash() or RootHash().
Discussion
-----------
A root NXOF object will be created by a protocol (like Noise), using h
= RootHash(protocolname, HASHLEN) followed by CreateNXOF(h).
These functions are split into two steps so that the output from
RootHash() can be used by the protocol in addition to creating child
NXOFs (e.g. as a Noise "h" value for channel-binding), or RootHash()
can create multiple NXOFs.
We defined a RootHash() function instead of a "primordial" NXOF object
to prevent such an object from being passed as an NXOF to subfunctions
- it should only be used at the beginning of a protocol to create a
root NXOF.
In more detail, Noise usage would be something like:
InitializeSymmetric:
h = RootHash(Noise protocol name, HASHLEN)
MixHash:
h = CreateNXOF(h).Hash(input, HASHLEN)
Calling a PQ KEM:
h, h' = CreateNXOF(h).Hash(empty, 2*HASHLEN)
nxof = CreateNXOF(h')
MixKey(KEM(nxof, ...))
The PQ KEM could derive additional children NXOFs from its NXOF input.
Or, it could just domain-separate its inputs to Hash() by prepending
labels.
Note that to created a "keyed" NXOF for MACs or PRFs we can simply
Hash(key) and then create a child NXOF from the output.
Implementing an NXOF
---------------------
Given an XOF like SHAKE128 or SHAKE256:
- An NXOF contains an internal "state" of HASHLEN bytes
- Define a primordial NXOF object with internal state of all-zeros
- Define RootHash as primordial.Hash
- Define CreateNXOF as state = input
- Define Hash(input, len) as XOF(state || input, len)
Given HKDF:
- As above, but HASH(input, len) is HKDF(salt=state, input, len)
Note that for existing hash functions, we wouldn't re-design all the
Noise hashing around an HKDF-based NXOF. But we could still provide
such an NXOF to crypto subfunctions like PQ KEMs.
One question is whether one could design NXOF crypto-primitives that
are more efficient than SHAKE-based or HKDF-based constructions. For
example, could there be a SHAKE variant that uses the "state" as as
the sponge's capacity, instead of prepending it to the sponge's rate?
Trevor
More information about the Noise
mailing list