[noise] Deriving resumption PSKs (was: SAS (was: Explicit nonces (for lossy transports))

Trevor Perrin trevp at trevp.net
Sat Jul 29 21:49:40 PDT 2017


> On Wed, Jul 12, 2017 at 10:20 PM, Rhys Weatherley
> <rhys.weatherley at gmail.com> wrote:
>> On Wed, Jul 12, 2017 at 6:44 PM, Trevor Perrin <trevp at trevp.net> wrote:
>>>
>>>  (B) One party can just transmit a PSK to the other.
> [...]
>>
>> My concern with transmitting the PSK's is that they are no longer "mutual" -
>> the sending party solely determines the value.


Let's try to settle this question of how clients should derive PSKs
from an initial session for 0-RTT PSK-based resumption.

A few options:

 (1) I've been proposing the server just transmit the PSK as
application data in the initial session, as this is simple and doesn't
change Noise.

 (2) SSL and TLS have historically used the "master secret" for
resumption, which is bad for forward-secrecy, as it means the initial
session could be decrypted if the stored "PSK" is leaked.

 (3) TLS 1.3 derives PSKs from a "resumption secret" itself derived
from the "master secret".  This is better, but still means that
resumed sessions could be decrypted as long as the original session is
kept alive and retains the resumption secret.

 (4) We've considered deriving PSKs via the same mechanism as rekey, e.g.

https://moderncrypto.org/mail-archive/noise/2017/001177.html
https://moderncrypto.org/mail-archive/noise/2016/000659.html

However I think connecting rekey and PSK derivation adds complications
(2nd email above).


Rhys criticized (1) because it's lacks a contributory property:  E.g.
if the server's RNG is bad and thus generates a weak ephemeral key, a
passive eavesdropper of Noise_XX might not be able to decrypt the
session (due to the good "es" DH with the server's static key).
However, this attacker might be able to guess the resumption PSK.  In
this case, deriving the resumption PSK from the session keys would be
more secure.

While this case isn't that important, it's an opening for criticism
and nitpicking we should probably avoid.

Since we recently added an optional 3rd output to HKDF for
MixKeyAndHash(PSK), it's now less painful to derive extra keys based
on the output of HKDF in Split().  So I'll propose using a chain of
HKDF to derive numbered PSKS (0, 1, 2, ...):

EK = 3rd output from Split().HKDF()
CK_PSK, PSK_0 = HKDF(EK, "PSK")
CK_PSK, PSK_1 = HKDF(CK, "")
CK_PSK, PSK_2 = HKDF(CK, "")
...

Now the server just has to say: "Use PSK #3 with this session ID /
session ticket", and the client can derive the same PSK.  PSK keys,
the current PSK "chaining key", and transport keys are all independent
wrt forward secrecy.

The extra key "EK" allows derivation of other keys for other purposes
via HKDF(EK, <whatever>).  HKDF is overkill here, but it means we
continue to use a single function for key derivation, so the
simplicity is probably worth it.

?

Trevor


More information about the Noise mailing list