nacl

hints
Login

hints

Hints

How does crypto_box work?

What happens if you use it multiple times?

If you take two fixed key-pairs, the result of the key exchange will always be the same.

But the symmetric part secret_box is secure even when you use a key several times, as long as you never reuse a nonce for that key, i.e. the (key, nonce) pair must be unique.

This property is pretty much the same for all modern authenticated stream ciphers, such as AES-GCM or XSalsa20-Poly1305.

Common ways to create a unique nonce are:

from https://stackoverflow.com/questions/13663604/questions-about-the-nacl-crypto-library

What key length does nacl::auth need?

Any. nacl::auth prepares the key the way RFC 2104 section 2 prescribes, so the length of the key you pass in does not have to match anything:

That matters wherever the secret is not generated locally: JWT, webhook signatures of GitHub, Stripe or GitLab, and API HMACs all use a secret of arbitrary length that the other side decides on.

RFC 2104 recommends a key of at least the hash output length but does not require it, and neither does nacl::auth. If a minimum key length matters in your context, check it before you call. nacl::randombytes auth -key produces 32 bytes.

Which of the five variants should be used?

option hash tag JWT
-hmac224 SHA-224 28 bytes --
-hmac256 SHA-256 32 bytes HS256
-hmac384 SHA-384 48 bytes HS384
-hmac512256 SHA-512 32 bytes NaCl crypto_auth, the default
-hmac512 SHA-512 64 bytes HS512

-hmac512256 is the NaCl primitive crypto_auth_hmacsha512256, HMAC-SHA-512 truncated to 32 bytes. It is the default of nacl::auth and the right choice when both sides are yours.

The other four are the HMACs RFC 4231 defines test vectors for, and they are what interoperability calls for: -hmac256, -hmac384 and -hmac512 are the HS256, HS384 and HS512 of JWT, and -hmac256 is behind nearly every webhook signature. None of them are interchangeable, the same key and message produce different tags.

Two pairs invite confusion. -hmac512 and -hmac512256 are the same computation, the second cut to 32 bytes, so one tag is the prefix of the other -- handing a truncated tag over as HS512 is a mismatch no peer accepts. -hmac224 and -hmac384 on the other hand are not prefixes of -hmac256 and -hmac512: SHA-224 and SHA-384 begin from a different initial state.

Why use nacl::auth verify instead of comparing the tags?

nacl::auth verify compares in constant time, through crypto_verify_32 and, for the longer tags, a second such call whose result is folded in with a bitwise or so that both halves are always looked at. The duration of the comparison therefore does not reveal how many leading bytes were correct. Comparing two tags with string equal or eq stops at the first difference and leaks exactly that. It returns 0 when the tag matches and -1 when it does not.