[noise] Noise replacements for crypto_box and crypto_secretbox

Trevor Perrin trevp at trevp.net
Sun Oct 2 01:24:23 PDT 2016


On Sat, Oct 1, 2016 at 9:35 PM, Brian Smith <brian at briansmith.org> wrote:
>
> A lot of people think the NaCl crypto_box and crypto_secretbox are great and
> want to use them. Totally reasonable. However, those things use Salsa20,
> which isn't supported by crypto libraries as ubiquitously as ChaCha20. Thus,
> I suggested we (the crypto community) should make things that are just like
> the NaCl stuff, except swapping ChaCha20 for Salsa20, and encourage people
> to use it.
>
> Trevor brought up the good point that Noise tries to do something like this,
> and it might be good to define that things as an instance of a Noise
> protocol. However, it isn't obvious that Noise covers all the same use cases
> as crypto_box and crypto_secretbox. Also, Noise has a lot of options, and it
> isn't clear exactly which combinations of Noise options are most directly
> replacements for crypto_box and crypto_secretbox.


Good topic - Noise was inspired by NaCl, so I'd like to see it work
for those cases:


crypto_secretbox is just "authenticated encryption" (AE):

https://nacl.cr.yp.to/secretbox.html

So you could implement it with any AEAD scheme that Noise supports
(e.g. ChaCha20/Poly1305, or AES-GCM) just by setting the "associated
data" (the "AD" in AEAD) to zero-length.

crypto_secretbox_xsalsa20poly1305 is interesting because it supports a
24 byte nonce, which is large enough to be randomly generated without
fear of collisions.  To support that, it uses a hash function derived
from Salsa20 to hash the key and the nonce into a new key.

Noise tries to make minimal assumptions on its underlying crypto
functions.  So a large-nonce AE in the style of Noise could just use
HKDF, e.g. with Noise's "HKDF" function:

crypto_secretbox(key, nonce, plaintext)
  k = HKDF(key, nonce)
  ENCRYPT(k, n=0, ad=zerolen, plaintext)

crypto_secretbox_open(key, nonce, ciphertext)
  k = HKDF(key, nonce)
  DECRYPT(k, n=0, ad=zerolen, ciphertext)

You could adapt the Noise naming convention, e.g.

  NoiseSecretBox_ChaChaPoly_BLAKE2s
  NoiseSecretBox_AESGCM_SHA512
  etc.

I don't know enough about the use cases, though:
 * Is re-using the same key with random nonces common enough to make
this worthwhile?
 * If the use cases are low-end devices, then you might prefer a more
integrated design like XSalsa20.  But then you have to customize it
for every cipher.

---

If you're using multiple crypto_boxes to build a protocol (like
CurveCP) then you'd want to understand Noise patterns.

But if your protocol is a single box, it should be easy to convert -
you'd just use Noise_N, Noise_K, or Noise_X, depending on the sender's
static public key:
  (N)one
  (K)nown to recipient
  (X)mitted to recipient

If you were using a crypto_box for case N, with an ephemeral key, this
is similar, though perhaps with small improvements (e.g. the Noise
ciphertext is broken into <= 64k chunks, for streaming decryption).

If you were using a crypto_box for cases K or X with a static sender
key, Noise adds an ephemeral key, giving better forward-secrecy and
authentication in case the sender's key is compromised, and
identity-hiding (in case X).

If you wanted to do static-static DH with caching of the shared
secrets for efficiency (like DNSCurve) you're out of luck.  Noise
insists you use ephemeral public keys for a handshake, since that's
usually the safest choice.

We could think about being more friendly to reuse of static-static DH,
but that's a less-conservative protocol pattern, so I'm not eager to
encourage it.

Alternatively, we've thought about generalizing Noise Pipes to support
PSK-based resumption, which can give similar performance, so that
might be a better option for cases that need extreme speed.

Trevor


More information about the Noise mailing list