Skip to content

Improve SecretConnection/STS KDF? #1165

@tarcieri

Description

@tarcieri

SecretConnection presently uses the NaCl crypto_secretbox construction for authenticated encryption:

https://github.com/tendermint/tendermint/blob/master/p2p/secret_connection.go#L131

crypto_secretbox decomposes to the following:

Salsa20Poly1305(HSalsa20(k, nonce), Ø{8}, frame)

The crypto_secretbox API imposes a 24-byte length requirement on the nonce, and for that reason SecretConnection first pre-hashes all of the cryptographic parameters with RIPEMD160:

https://github.com/tendermint/tendermint/blob/master/p2p/secret_connection.go#L131

So the overall construction ends up looking like this:

Salsa20Poly1305(HSalsa20(k, RIPEMD160(lowPubKey || hiPubKey)), Ø{8}, frame)

(glossing over the sender/receiver nonce tweaks momentarily)

So, funny thing, my understanding is HSalsa20 is just a PRF and can accept variable length input. The 24-byte restriction is a totally arbitrary one imposed by the crypto_secretbox API. So if you wanted to get rid of RIPEMD160 (see discussion here), you could just do this:

Salsa20Poly1305(HSalsa20(k, lowPubKey || hiPubKey), Ø{8}, frame)

Tada, no need for RIPEMD160. If you step outside the constraints of the crypto_secretbox API, you should just be able to pass everything directly to HSalsa20. This should provide a 2128 security level, as opposed to the 280 one provided by RIPEMD160.

All that said, I would probably suggest using HKDF instead of HSalsa20 here. See some of the criticism CodesInChaos makes about the similar nonce-based approach used by CurveCP:

https://codesinchaos.wordpress.com/2012/09/09/curvecp-1/

A more traditional way to build an authenticated key exchange is to compute a transcript hash of the entire key exchange and use that as an input to something like HKDF, and using that to derive symmetric keys.

HKDF is an extremely boring construction with well-understood, provable security properties created by Hugo Krawczyk, who just so happened to be this year's Levchin Award winner at RealWorldCrypto. HKDF is used by both TLS and Noise for key derivation.

With HKDF, instead of tweaking the nonce and using that to derive two keys, you can just ask for two symmetric keys worth of output, and have the conversation participants pick the appropriate key for their side of the conversation.

HKDF for Go is available here:

https://godoc.org/golang.org/x/crypto/hkdf

A minimalistic change to HKDF might change the above to something like this:

derivedKey = HKDFSHA256(k, lowPubKey || hiPubKey, "COSMOS_SECRETCONNECTION_KDF")
Salsa20Poly1305(derivedKey, Ø{8}, frame)

Metadata

Metadata

Assignees

Labels

C:p2pComponent: P2P pkgS:proposalStatus: ProposalT:securityType: Security (specify priority)

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions