Friday, January 14, 2011

How to generate encrypted shadow password

I recently had a need to generate some encrypted passwords to store in a Kickstart file. This seemed like it should be a fairly straight forward task but it stumped me for a bit. Basically, I needed to take a plain text password and encrypt it as part of the rootpw or user option in the Kickstart file. My initial search of how to do this lead me to many quick solutions. However, upon closer look, the quick solutions only seemed to point to how to generate an MD5 hashed password. I really wanted a SHA512 hash. So, I continued my search -- And found nothing useful. Do not get me wrong. I found many ways of using PHP, database utilities, optional packages, and even some strange shell scripts that would essentially become utilities of their own. I finally gave up on my search and decided to figure it out. The search wasn't completely a waste of time because the information I gained during my search allowed me to come up with a solution. The solution was based on combining information I read within the crypt() method along with information I found on how to generate MD5 hashes.
Two simple methods, choose one that best fits your need:
python -c 'import crypt; print crypt.crypt("Red Hat", "$6$somesalt$")'

perl -e 'print crypt("Red Hat", "\$6\$somesalt\$") . "\n"'

In both methods, the first parameter value of Red Hat is my plain text password that I want to generate a hash for. The second parameter is the salt needed by the crypt() function. The salt is what is very important here. It must start out with $6$ followed by a salt value, followed by a $. The $6 tells the crypt function to use SHA512 and the second $ serves as a delimiter between the hash method and the actual salt. The last $ is needed because it is what appears in the shadow password as a delimiter between the salt and the actual hash. So, if we looked at a shadow password:
$6$somesalt$rkDq7Az4Efjo.0vtRe7E/8UXZNB6.88eMNIaqLdpmULIFkw3gDNPFnjAX4Y9fiGFzVlOyaDr1X.YYUsczCeMH.

The 6 defines the hash algorithm that was used. In this case, SHA512. The somesalt defines the actual salt that is used to generate the hash. The dollar-sign ($) is not used as part of the salt. Finally, the remaining string after the third dollar-sign ($) is the actual hash.
When invoking the crypt() method, essentially the same format applies. Within the salt parameter value, you can define the salt along with the hash algorithm to use. In the case of the perl command, the dollar-signs ($) had to be escaped.

6 comments:

Tolbkni Kao said...

Great thanks! the post help me!

matt0177 said...

This just helped me A LOT!

Aamir Raza said...

As i tested in python -c command if we converted the string which has @ sign it works fine..
But in case of perl script the string which has @ sign in it doesn't work.

Tested on ubuntu 12.04 and centos 6.3
Example For Password string:pass@123
Plain Strings works fine:pass
! sign also works fine for both..

Unknown said...

@Aamir Raza that is because in Perl, the @ symbol is the array prefix. Therefore, you must escape it.

string:pass\@123

Unknown said...

Thanks for the technical overview, and the advice with details.

I wrote a linux shell script to generate some hashes based on your input.

Thanks again.

Unknown said...

@Warron French, glad it helped! Personally, I was surprised to see that there wasn't already a utility or shell script available within the most popular distros that did this already. Or at least, I could not find one.