[noise] new branch: psk2

Trevor Perrin trevp at trevp.net
Fri Nov 13 23:16:44 PST 2015


https://github.com/trevp/noise/blob/psk2/noise.md

I realized a problem in how we were using ephemerals as nonces.  So
I'd like to eliminate encryption of ephemeral public keys, and also
streamline PSK by using ephemeral public keys in place of explicit
randoms:


 * A few months back we changed to allow encryption of ephemerals,
e.g. in Noise_IK the responder's ephemeral would be encrypted.
Unfortunately, if the initial message was replayed, encryption of the
responder's ephemeral will not be secure (key reuse).

There was no strong rationale for encrypting the responder's
ephemeral, this was mainly done to simplify the logic.  So there's no
real problem if this encryption is weak, but it seems bad form.

We could address this by always using explicit nonces in this
situation, but then we're making the protocol less efficient just to
shore up this unimportant encryption.

So this branch changes back to unencrypted ephemerals.


 * Instead of sending an explicit random for pre-shared keys, changed
it to MixKey(e.public_key) when sending/receiving an ephemeral with
PSK.  I don't have patent worries about mixing ephemeral public keys
into the session key, and this is simpler and eliminates the explicit
randoms, so PSK messages are the same size.

This makes it crucial for each party's first message to begin with
"e", so I reordered "s, e" -> "e, s" in a couple patterns, and
explained this in Section 6.1 "Pattern validity".


 * A more subtle "invalid" pattern would be one that sent encrypted
data without first doing a DH with the sender's ephemeral against any
public keys the remote party has sent.  Example:

 -> e, s
 <- e, dhee, dhss

This could be insecure if the DH function allows a public value with
small order, e.g. with the traditional Curve25519 DH function an
attacker could send a value which forces the output to zero.  If a
bogus initiator repeatedly sends such an "e", then the responder's
dhee randomization will fail, and there will be key reuse based on the
dhss key.

The IETF is contemplating ECDH functions that perform an explicit
check of the output against zero, but that introduces other issues
(more complex, not all existing implementations do this, not all DH
functions necessarily do this, the check should be const-time, need to
research point validation patents, etc).

So I think it's better to be secure even in the face of this behavior.
If we require a "valid" pattern to include DH from sender's ephemeral
against all recipient public keys, the problem disappears:

 -> e, s
 <- e, dhee, dhes, dhss

Forcing dhee to 0 doesn't prevent dhes from randomizing things.  Using
bad s and e to force all DH ops to 0 isn't an attack, and if a PSK is
introduced, it still gets randomized appropriately by
MixKey(e.public_key).

That's a bit complicated of an analysis, and imposing these conditions
on the patterns creates some risk of misuse.  The upside is efficiency
and simplicity when using correct patterns, which feels more
important.


Trevor


More information about the Noise mailing list