[noise] Draft extension: Additional key material in transport phase

str4d str4d at i2pmail.org
Sun May 27 22:19:03 PDT 2018


Hi all,

This is the third of three draft extensions I've been working on, as
part of designing the new Noise-based TCP transport for I2P [0]. Note
that I'm using the term "extension" loosely - I don't know exactly how
these would best fit into the ecosystem.

I look forward to your feedback!

Cheers,
str4d

[0] https://geti2p.net/spec/proposals/111-ntcp-2

---

# Noise extension: Additional key material in transport phase

## Motivation

At the end of the handshake phase of a Noise protocol (once all message
patterns have been consumed), Split() is called to obtain a pair of
CipherState objects for use in the transport phase. These objects are
initialized with key material derived from the final value of the
handshake chaining key ck (using HKDF(ck, zerolen, 2) to obtain two keys).

In some cases, it is desirable to derive additional key material for use
in parallel with the CipherState objects. For example, when using
SipHash to derive an XOR mask byte stream to hide the length field of
Noise transport messages (as in obfs4), six u64 values are required to
initialize SipHash (two keys and an IV for each direction).

For simplicity, this extension proposes deriving two additional keys:
one for use with the data stream encrypted by the first CipherState
object, the other for use with the data stream in the opposite direction
(encrypted by the second CipherState object). Further derivations of key
material from these two additional keys is likely to be
protocol-specific, and is therefore out of scope.

An alternative proposal could be to alter CipherState to support
deriving additional keys from its internal key. However, the author felt
it was safer to extend the existing key derivation process within Noise.

## Changes to the Noise specification

The definition of the function HKDF is modified to read:

- HKDF(chaining_key, input_key_material, num_outputs): Takes a
  chaining_key byte sequence of length HASHLEN, and an
  input_key_material byte sequence with length either zero bytes, 32
  bytes, or DHLEN bytes. Returns a tuple of byte sequences, each of
  length HASHLEN, depending on whether num_outputs is two, three, or
  four:
  - Sets temp_key = HMAC-HASH(chaining_key, input_key_material).
  - Sets output1 = HMAC-HASH(temp_key, byte(0x01)).
  - Sets output2 = HMAC-HASH(temp_key, output1 || byte(0x02)).
  - If num_outputs == 2 then returns the pair (output1, output2).
  - Sets output3 = HMAC-HASH(temp_key, output2 || byte(0x03)).
  - If num_outputs == 3 then returns the triple (output1, output2,
    output3).
  - Sets output4 = HMAC-HASH(temp_key, output3 || byte(0x04)).
  - Returns the tuple (output1, output2, output3, output4).

A new function is added to SymmetricState:

- SplitAk(): Returns a pair of CipherState objects for encrypting
  transport messages, along with a pair of additional keys. Executes the
  following steps, where zerolen is a zero-length byte sequence:
  - Sets temp_k1, temp_k2, ak1, ak2 = HKDF(ck, zerolen, 4).
  - If HASHLEN is 64, then truncates temp_k1 and temp_k2 to 32 bytes.
  - Creates two new CipherState objects c1 and c2.
  - Calls c1.InitializeKey(temp_k1) and c2.InitializeKey(temp_k2).
  - Returns the tuple (c1, c2, ak1, ak2).

WriteMessage() and ReadMessage() are modified to support optionally
returning the additional keys by using SplitAk() instead of Split().
This modification is implementation-specific.

## Example implementation

https://github.com/str4d/snow/tree/split_ak

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


More information about the Noise mailing list