SHA512 salted hash from mkpasswd doesn’t match an online version

encryptionhashsumpasswordshadow

I'm puzzled by the hash (ASCII) code stored under Linux (Ubuntu) /etc/shadow.

Taking a hypothetical case, let password be 'test', salt be 'Zem197T4'.

By running following command,

$ mkpasswd -m SHA-512 test Zem197T4

A long series of ASCII characters are generated (This is actually how Linux store in the /etc/shadow)

$6$Zem197T4$oCUr0iMuvRJnMqk3FFi72KWuLAcKU.ydjfMvuXAHgpzNtijJFrGv80tifR1ySJWsb4sdPJqxzCLwUFkX6FKVZ0

When using online SHA-512 generator (e.g. http://www.insidepro.com/hashes.php?lang=eng), what is generated is some hex code as below:

option 1) password+salt

8d4b73598280019ef818e44eb4493c661b871bf758663d52907c762f649fe3355f698ccabb3b0c59e44f1f6db06ef4690c16a2682382617c6121925082613fe2

option 2) salt+password

b0197333c018b3b26856473296fcb8637c4f58ab7f4ee2d6868919162fa6a61c8ba93824019aa158e62ccf611c829026b168fc4bf90b2e6b63c0f617198006c2

I believe these hex code should be the 'same thing' as the ascii code generated by mkpasswd. But how are they related?

Hope someone could enlighten me?

Best Answer

On Ubuntu/Debian mkpasswd is part of the package whois and implemented in mkpasswd.c which as actually just a sophisticated wrapper around the crypt() function in glibc declared in unistd.h. crypt() takes two arguments password and salt. Password is "test" in this case, salt is prepended by "$6$" for the SHA-512 hash (see SHA-crypt) so "$6$Zem197T4" is passed to crypt().

Maybe you noticed the -R option of mkpasswd which determines the number of rounds. In the document you'll find a default of 5000 rounds. This is the first hint why the result would never be equal to the simple concatenation of salt and password, it's not hashed only once. Actually if you pass -R 5000 you get the same result. In this case "$6$rounds=5000$Zem197T4" is passed to crypt() and the implementation in glibc (which is the libc of Debian/Ubuntu) extracts the method and number of rounds from this.

What happens inside crypt() is more complicated than just computing a single hash and the result is base64 encoded in the end. That's why the result you showed contains all kinds of characters after the last '$' and not only [0-9a-f] as in the typical hex string of a SHA-512 hash. The algorithm is described in detail in the already mentioned SHA-Crypt document.

Related Question