[noise] NoisePSK

Trevor Perrin trevp at trevp.net
Thu Nov 12 11:24:50 PST 2015


On Thu, Nov 12, 2015 at 4:31 AM, Jason A. Donenfeld <Jason at zx2c4.com> wrote:
> For example, for the DoS protection in a
> NoiseIK, before being able to discard the message upon attempted
> decryption/authentication of the first public ephemeral, this would
> result in:
>
> MixHash(handshake || prologue) - 1 hash
> MixHash(pubkey) - 1 hash
> HKDF(psk, none) - 6 hash
> MixKey(psk1) - 6 hash
> MixHash(psk2) - 1 hash
>
> 15 hashes in total. I don't have any numbers, but I imagine this is
> still computationally preferable to a single DH, but still, it's an
> awful lot.

Don't follow your counting - also, you should look at some real timing
data, hashing is fast.

To look at your case a little more, let's count the number of "blocks"
that are hashed, and consider padding (e.g. for SHA256 HASHLEN=32,
BLOCKLEN=64, but minimum 9 bytes padding):

# Processing handshake_name, prologue, psk
# Assuming handshake_name > HASHLEN, HASHLEN=32, BLOCKLEN=64

ck = h = HASH(handshake_name)  # probably 1 block
h = HASH(h || prologue)        # probably 1 block
ck, k = HKDF(ck, psk)          # probably 12 blocks
h = HASH(h || k)               # 2 blocks (using optimization I just posted)

# Process pre-message
h = HASH(h || server_static_pubkey)  # 2 blocks

[EVERYTHING PREVIOUS CAN BE PRECALCULATED]

# Process client random
ck, k = HKDF(ck, random)       # 12 blocks

So 30 blocks * 64 bytes/block * ~10 cycles/byte ~ 20K cycles.  Your
server could precalculate everything but the client random HKDF, which
would eliminate 60% of the hashing.  I think that's pretty efficient.


> For better DoS protection, you could add another aspect - a 32 byte
> MAC from Keyed-Blake2 over all the previous bytes of the handshake
> message, as the last field, that uses the psk as a key. This way
> invalid messages could be discarded after a single keyed-hash
> operation, instead of 15.

You could add that, but I don't think that's general enough to be
consider for Noise.


> Terrific. The way I'd probably go about using this is that for users
> who don't provide a PSK of their own, I'll automatically use
> "initiator.static_public || responder.static_public" as the PSK. This
> way, so long as the public keys stay secret or are forgotten about
> before the advent of a quantum computer / DH cryptographic advances,
> the messages automatically remain safe. What do you think of that
> idea? Is it as safe as I'm hoping?

You could do that, if you want to manage your public keys as secrets.

Trevor


More information about the Noise mailing list