Closed enclave-marc-barry closed 1 month ago
True, libsodium chooses a value of 32 bytes here. But RFC 2104, Section 3 clearly says that a key length of less than 64 bytes reduces the security strength of HMAC-SHA-512.
Of course, if you want a lower level of security, you can choose lower values. So I think there is no right or wrong with the constants unless you specify your desired security level.
Based on my reading of the RFC, it seems to me that the best strategy for a lower security level is to choose a key length of 64 bytes and then vary the length of the authentication tag. That's what’s currently implemented in HmacSha512
.
This RFC was published in 1997, and written years before that. MD5 was the holy grail back then, and 5 years before SHA2 was announced.
The recommendation to have a key as large as the block size comes from the fact that the only proof that HMAC could act as a PRF was using that setting. For any reasonable output size (~ >= 192 bit) that all contemporary hash functions support, the output is indistinguishable from random, so theoretical PRF security doesn't do anything. Truncating the output also immediately achieves PRF security.
More importantly, it has been proven that HMAC offers PRF security with any sufficiently large key length (see When Messages are Keys: Is HMAC a dual-PRF?).
There's absolutely no point in using 512 bit keys. Or to use 512-bit authenticators for that matter. A 256 bit authenticator already guarantees that collisions will never occur.
For all these reasons, I'd recommend just using the regular high-level crypto_auth
functions, which uses HMAC-SHA512 and truncates the output.
Thanks both for the insightful replies, much appreciated.
So I think there is no right or wrong with the constants unless you specify your desired security level.
I think that's sort of my point @ektrah, in NSec the MinKeySize
is initialised to 64U
, whereas in libsodium the minimum is 32U
. Regardless of the discussion around key length efficacy, for me it is incorrect to force (without option to override, unless I'm mistaken?) a different set of constants on the user vs. those defined in libsodium.
It looks like there's a constructor signalling intent to allow adjustment of keySize
, but from my reading both the MinKeySize
and MaxKeySize
constraints are set to 64
, so I'm not seeing any practical use for the constructor?
Apologies in advance if I'm missing something obvious.
Thanks @ektrah!
Looking at
src/Cryptography/HmacSha512.cs
in NSec, I note the comment on lines 24-28 referring to minimum keySize for this function being 32 bytes.Checking the constants defined in libSodium, we can see this is indeed the case in crypto_auth_hmacsha512.h#L19 for the
crypto_auth_hmacsha512_KEYBYTES
constant:But looking back into
src/Cryptography/HmacSha512.cs
it seems to me there might be a mistake. Both minimum and maximum key sizes are set by the same libsodium constant.It appears that both
MinKeySize
andMaxKeySize
are set to the length ofcrypto_hash_sha512_BYTES
(64U
) exported from libsodium, which is not equivalent to thecrypto_auth_hmacsha512_KEYBYTES
(32U
) value referenced in the nsec comment, nor the value used in libsodium, and therefore I believe also not the correct constant to set here forMinKeySize
.It appears that the library correctly uses
crypto_hash_sha512_BYTES
to setMaxKeySize
, but by using that same value to also setMinKeySize
the API is incorrectly preventing the use of 32 byte keys with the HmacSha512 function.I believe it should be:
Happy to raise a PR if you concur. Also @ektrah, thank you for maintaining this library!