SHA-512 crypt specs reports that SHA-512 crypt uses 128bit salt.

The FreeBSD/Linux password generation code builds the salt using 16 bytes random data (128bits) and then it translates the random data using something like the B64 encoding (which is a base64 variation).

An advisor is reporting that:

because of the cardinality of the subset, each character represents 6 bits of information. Having a salt of size 16 characters generated by this method gives 16x6 = 96 bits of pseudo random data.

In conclusion it looks like the salt of this implementation uses only 96 bits.

I don't agree with this because here the B64 is just used to have printable characters. The random values are used to pick up a valid character. Base64 encoded string grows in length, here we have the same length. The random string is then used as it is by the SHA-512 implementation (where it pass a 128 bit value).

Can somebody confirm the advisor statement and explain more?


Analysis of the C code is off-topic. It outputs a string of SALTSIZE=32 characters each obtained by indexing a string of 64 base-characters encoded in ASCII as a single byte. The indexes are obtained according to the low-order $4\times6$ bits of what seems to a pseudo-random 32-bit value produced by arc4random().

Thus the output is a 32-byte bytestring (not counting the string terminator character/byte) with each byte drawn from a set of 64, thus $32\times8=256\,$bits, with $32\,\log_2(64)=192\,$bits of entropy (at most, assuming full-entropy source).

I conclude neither "16x6 = 96 bits of pseudo random data" nor "128 bit value" apply to what the linked code produces. But wait, the linked specification tells

For the SHA-based methods the SALT string can be a simple string of which up to 16 characters are used.

which suggests that something (at least, the code that does cryptography with the salt) should truncate that 32-character salt to 16. In which case there remains a 16-byte bytestring with each byte drawn from a set of 64, thus $16\times8=128\,$bits, with $16\,\log_2(64)=96\,$bits of entropy (at most, assuming full-entropy source).

That matches what the advisor states, although the end could be restated more clearly with "gives 16x6 = 96 bits worth of pseudo random data".

The statement "Base64 encoded string grows in length" applies to Base64 encoding, not to what the code does.

Addition per comment:

Should this be formally a 128 bit salt or a 96 bit salt?

My (debatable) position: after truncation to 16 characters, the salt is 128-bit with $2^{96}$ possible values, thus to be considered (at best) as effective as a 96-bit uniformly random salt with full entropy from the standpoint of preventing pre-computations. Which is way enough.

  • $\begingroup$ Thanks a lot, here salt is truncated to 16 chars. So at the end we have a 128 bit long salt generated from a 96 bits of entropy. Should this be formally a 128 bit salt or a 96 bit salt? $\endgroup$ – JohnP Nov 16 '20 at 11:13
  • $\begingroup$ @JohnP: see updated answer. Notice that on second though, I think that what the advisor states ought to be clarified by strategically adding "worth". $\endgroup$ – fgrieu Nov 16 '20 at 13:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.