[noise] Resumption PSKs

Trevor Perrin trevp at trevp.net
Mon May 23 10:55:40 PDT 2016

Currently Noise has the ability to use a PSK, but we don't say where
PSKs come from.

One case we'd like to support is compound protocols similar to Pipes
or TLS resumption, where a PSK is established in an initial "full"
handshake, then used for a "resumption" handshake.  This allows
low-end devices to do symmetric-key resumption with fewer DH
operations (even zero).

Obviously, the server could transmit an explicit PSK value.  It could
also transmit the "sesson ID" or "session ticket" that the client has
to present back to the server to identity the PSK (session IDs are
indexes into a server's session cache; session tickets are for
stateless servers that just encrypt the resumption state with a
session ticket key).

It would be more efficient if these values could be derived, not
transmitted (this isn't possible for a session ticket, but is possible
for a PSK and session ID).

TLS just stores the original master secret (similar to Noise's final
ck).  That's a bad design because it reduces forward secrecy of the
original connection.

TLS 1.3 is planning to store a value derived from the original master
secret.  This is better, but it means the parties need to know at the
time of handshake whether resumption is desired, and have to store
this value for the lifetime of the initial connection.

Because this is for low-end devices, we'd like to be more efficient,
and only extract the resumption secret from the transport keys if and
when it's needed.  For example:

  resumption_secret = ENCRYPT(k, 2^64-1, "", zeros[32])[0..32]

We're using the last nonce value (2^64-1), so this reduces the number
of possible transport messages by 1, but that's not a big deal.

We're encrypting 32 bytes of zeros, then taking the first 32 bytes of
ciphertext as the resumption secret.  With the current ciphers, that
allows skipping the GMAC or Poly1305 calculations.

It's possible that we'd extract a 32-byte resumption key, then later
decide we also wanted to extract a 16-byte session ID, or other values
for other purposes.  So we could extend this to support extracting a
sequence of random values of length N[1], N[2], etc:

  k[1] = k
    output[i], k[i+1] = ENCRYPT(k[i], 2^64-1, "", zeros[N[i]+32])

In other words:  By calling ENCRYPT() on 32 extra bytes of zeros, we
also get a new key which can be used for extracting the next value,
and this can be repeated to extract an arbitrary-length sequence of
output values.

So this would give us the ability to extract additional keys from the
transport keys, with fairly low cost (it costs nothing if not used,
but you can extract values whenever you want, and you can always
extract additional values later, when you discover the need for it).


More information about the Noise mailing list