jedisct1 / libsodium

A modern, portable, easy to use crypto library.
https://libsodium.org
Other
12.06k stars 1.72k forks source link

crypto_generichash_blake2b_salt_personal takes 16 byte input but docs say the input must be 8 bytes #1229

Closed 0x4f53 closed 1 year ago

0x4f53 commented 1 year ago

Our team was working on a key derivation function based on libsodium's crypto_generichash_blake2b_salt_personal(). We noticed the docs mentioning that the ctx is supposed to be 8 characters, and thus 8 bytes (1 char = 1 byte in C). However, the actual function in the library takes a 16 byte input.

What's also weird is that if we supply an 8 byte ctx while it's expecting 16 bytes, we don't get an error of any kind telling us that the context is of incorrect size. This can have major consequences for those following the docs.


We decided to use crypto_generichash_blake2b_salt_personal() since the default crypto_kdf_derive_from_key() function only supports a 32 byte master_key and we wanted to derive keys from a 64 byte master_key input.

We stumbled upon this after 5 days of scratching our heads over why we were getting a different hash each time for the exact same parameters. We are using LazySodium-Android, which is a Java wrapper for libsodium. We tried several things, including empty ByteArrays, passing unsigned integers, and more. We observed that the hash was different each time, but sometimes, it would be correct and then change again randomly.

When we changed the context from an 8 character string to a 16 character string, the issue was completely gone. Had we caught an exception telling us that the context is of incorrect length, we could've avoided a lot of trouble.

jedisct1 commented 1 year ago

The link you are mentioning is for the crypto_kdf_derive_from_key() function. And the documentation seems correct. The context size is crypto_kdf_CONTEXTBYTES, which is 8.

crypto_generichash_blake2b_salt_personal() is a low-level function, with different parameter limits.

Like all functions, the parameters come with constants representing the limits and expected sizes. Here, for the personal parameter, this is crypto_generichash_blake2b_PERSONALBYTES.

jedisct1 commented 1 year ago

That being said, if that Java wrapper accepts inputs of incorrect sizes, this is an issue you should report to that project.

That shouldn't be possible in a language like Java.