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.