At work, we use NIS for central UNIX authentication, but server accounts with elevated rights (admin accounts) are actually local, with their own passwd entry. When the NIS password changes (forced password expiry) then I need to request a sync of the new password from NIS to all servers where I have a local account. That is done by syncing the password hash, so that I do not have to enter my plaintext password anywhere along the process – it is fully automatic.
My password had to change again recently, and that made me consider how the encrypted hashes are actually created. Worthwhile writing that info down in a blog article I think.
On Slackware Linux, we use “/etc/shadow” instead of /etc/passwd to store the password of our user account. The shadow file is not accessible (readable) by regular users, therefore it is not possible to retrieve someone’s encrypted password hash… which would be the ideal catch for a password thief. Brute force cracking tools exist that will yield the plaintext password eventually. So, the shadow suite makes our life more secure.
How does this process work of creating and storing a password at first, and later offering those same credentials to the login program in order to be allowed entrance? When logging in, you enter your username and the plaintext password. Your computer will use that plaintext password to compute an encrypted “hash” value and compare that computed hash with the hash value that is stored in “/etc/shadow”.
My example username will be “alien” and the password will be “Christmas.2014”:
The entry for the account “alien” in the /etc/passwd file looks like this:
alien:x:1001:100:The Alien,,,:/home/alien:/bin/bash
In the UNIX passwd file, every line consists of a series of fields separated by colons (:), see passwd(5) man page. The second field is where UNIX would store the password hash in pre-shadow times. Nowadays, only an “x” character is stored in that field because the actual password hash is stored inside the shadow file. So, the entry for the same account in /etc/shadow looks like this:
alien:$5$QIGCa$VJ16x81oLReQLHBzU60ADKlJoAdXVUJiSSB5FMgtfe.:16069:0:99999:7:::
You see that the password field in the shadow file (which is also the second field) is “$5$QIGCa$VJ16x81oLReQLHBzU60ADKlJoAdXVUJiSSB5FMgtfe.”. This value is the password hash. It can be de-constructed further. If we find out how this hash is constructed we will understand how our password will be checked and accepted at login. It will also become clear why you can try setting your password to the same value several times, and yet the hashed password will be different every time.
To start, let’s first look at the older Slackware releases. Chances are, if you have been upgrading your computer for years, you still have a password hash which stems from the old age. Slackware used to use a MD5-crypt encryption algorithm which is no longer considered secure. We’ll get to the current encryption scheme at the end of our example.
For our user “alien” with his password “Christmas.2014”, a MD5-crypted hash for the password would be: “$1$KdieS$8tz7obSJVIVegXsUtXxkq/”. You will probably have noticed that this hashed password is not simply a MD5 hash like “5ce3f04e74c0bc0d2e791ea0f47f5de0”, which can be obtained by running “echo -n Christmas.2014 | md5sum”. The MD5-crypt algorithm does a lot more.
For one, it uses a “salt” to randomize the hash value and make it harder for password crackers to crack your password with brute force. So in fact your password hash is being constructed not just from your plaintext password but additionally a salt string (a random string of characters) is used as input for the encryption.
When you set or change your password, you enter the plain text password and your computer generates a random string to use as the salt value. The computed hash is therefore different every time you change your password, because the salt will be different every time! And the salt string with which your password was encrypted is used every time you login: by combining the plaintext password you provide at the login prompt with the original salt string, the system computes your password hash and compares that string with the string stored in the shadow file. If the two match, you are allowed entrance. Simple and elegant.
But how does your computer know which salt string was used in the first place? That is actually also simple and elegant: the salt is stored as part of your hashed password, in the shadow file! Visible only to root, it is safe from snoopers.
Time to dissect the password hash and show you how this is achieved. The hash “$1$KdieS$8tz7obSJVIVegXsUtXxkq/” consists of three distinctive sections separated by ‘$’ characters:
- $1$KdieS$8tz7obSJVIVegXsUtXxkq/
- The ‘$’ characters are separators
- $1$KdieS$8tz7obSJVIVegXsUtXxkq/
- The ‘1’ indicates that the hash was generated with the MD5-crypt algorithm. Different string means different algorithm.
- $1$KdieS$8tz7obSJVIVegXsUtXxkq/
- The string ‘KdieS’ is the actual salt string that was used to compute the hash
- 1$KdieS$8tz7obSJVIVegXsUtXxkq/
- The string ‘8tz7obSJVIVegXsUtXxkq/’ is the hash which was computed from the plaintext password combined with the salt.
In case you are wondering if you can create these hashes yourself, yes you can! Sometimes that can be useful in scripts. Here are two commands to generate the MD5-crypt hashes from the above example password (Christmas.2014) and the salt shown earlier (KdieS):
$ openssl passwd -1 -salt KdieS Christmas.2014
$ perl -e 'print crypt("Christmas.2014", "\$1\$KdieS"),"\n"'
Unfortunately this will not work to generate the hashes you will find in the shadow file of Slackware 14.0 and later. If you look closely at the hash value in the beginning of the article “$5$QIGCa$VJ16x81oLReQLHBzU60ADKlJoAdXVUJiSSB5FMgtfe.” you will see that there is a ‘5’ instead of a ‘1’ inbetween those first two dollar signs. A bit of deduction and your comclusion will be that probably a different encryption than MD5-crypt will have been used?
As of Slackware 14.0, SHA256 (with default of 5000 rounds) is used to hash new passwords. These parameters are controlled by “ENCRYPT_METHOD” and “SHA_CRYPT_{MIN,MAX}_ROUNDS” in the file “/etc/login.defs”. Salt prefix $6$ corresponds to SHA512. And the blowfish patches to glibc use $2a$ for their prefix (according to user mancha on LQ).
The $5$ prefix means that SHA-256 is used for hashing. My Slackware laptop creates a hash with $5$ prefix which means SHA-256 was used. However, the hash of my own password still has a $1$ prefix… carried over through years of upgrading without re-installing obviously…
The openssl and perl commands I showed earlier are not able to generate hashes using SHA hashing algorithms, but there is a Python command that does the trick:
$ python -c "import crypt, getpass, pwd; print crypt.crypt('Christmas.2014', '\$5\$KdieS\$')"
Finally, let me tip you on a command which will be useful when you need to update user passwords in a script. The “chpasswd” utility accepts lines on its input that have the format “username:password” and will set the password for that user in the shadow file using SHA256 hashing algorithm (or any other supported algorithm), as follows:
# echo "alien:Christmas.2014" | chpasswd -c SHA256
Have fun digesting this! Eric
Recent comments