NavigationUser loginSpam?See spam posts on this site? If so, please don't reply to the spam! Instead, just report the URL to the webmaster. |
Password encryption with PerlI have a website where I want to be able to allow users to log in using their usernames and passwords which have been imported into a MySQL table from the /etc/passwd and /etc/shadow files on a different (Debian) server. Importing the data is no problem; the difficulty is in checking whether the password the user provides matches the hashed version stored in the table. I'm using a Perl script to do the checking; I've played around with the crypt() function, but the resulting hashes are much shorter than, and totally different to, the stored ones. Can anybody suggest what I can do? Thanks a lot. Tony. |
read about 'shadow password'
You'll have to look for documentation on the specifics of the latest version of shadow password. Basically it goes something like this:
1. The password field in /etc/passwd is replaced by an 'x'.
2. The actual password has a 'salt' attached to the beginning, is padded to an integral 'cipher block size', and the hash is taken.
3. The 'salt' and hash are stored as a string in the shadow password file.
So, you need to find out what the salt is (how many bytes, what values are allowed), what the padding scheme is (zero, or what-not - whatever it is, it may not be random), and what hash algorithm is currently used.
To do the opposite of course, you take the password, attach the salt (from the shadow passwd file), pad it, take the hash - and if the salt+hash matches the string in the shadow file then you know you have the correct password.
Just one note of caution: you must exchange passwords (preferably also user names) over a secure connection - no point in sending username and password in the clear - you may as well not have any passwords on the remote system in that case.
read about 'shadow password'
OK, thanks for that.
On my 32-bit Debian Sarge test machine, which uses the default encryption system, the pasword hashes are all 34 characters long, and all start with the 3-byte string $1$. The character set used seems to be [0-9a-zA-Z$/.] (not including the brackets). For example, the hash corresponding to the password "testuser" is "$1$1ZbgU0Hh$RgUUgvH/yYYsj.8YP0nQR0".
The algorithm used is not clear. Most of the docs I've seen (from a web search) suggest crypt() is used, but MD5 and DES are also mentioned. I have tried the following methods, none of which provide any useful result:
Can anybody point me in the direction of documentation about the algorithm used by the default Debian Sarge encryption system?
Thanks a lot.
Tony.
$world=~s/war/peace/g;
make sure you have the right variety...
The GNU 'crypt' doesn't quite behave like the original:
man 5 shadow
man 3 crypt
The $1$ indicates that an md5 hash is used rather than DES encryption. DES is reversible (you can retrieve an actual password) while md5 is a 1-way hash. At any rate, feeding the appropriate input to GNU crypt should give you the correct results.
Look at other authentication options - can you do it via LDAP or PAM? I don't know exactly what you want to do, but from what you've written so far I would think that LDAP is more suited to your job. You really don't want to copy the shadow file from another computer - it's very unhealthy for the other computer because you are bypassing some security features of the shadow file. It also guarantees that your database of user/shadow is out of sync with the server's actual user/shadow information.
read about 'shadow password'
Ah yes, the Perl version of crypt() works. In the case of the example given, I need to use the salt "$1$ZbgU0Hh", which gives the correct output.
What I'm doing is developing a remotely-hosted website for the company's staff to use for stuff like customer account enquiries when they're on the road. They're about as non-tech as you can get, so it would be much simpler for them to use the same login credentials on the site as they do back at base. The site would be updated every night, which is often enough.
Thanks a lot.
Tony.
$world=~s/war/peace/g;
LDAP still looks good
You can still have that remote site use LDAP for authentication; it just takes the name and password and the LDAP client does the rest. Only you can assess the security risks of your sites, but I'm just incredibly paranoid about having one system's secret information available directly on another system.
LDAP still looks good
I'll certainly look into LDAP; I've never used it before. However, the company's local server is hidden behind a dynamic IP and NAT, so remote access is not an issue, and I'm the only techie on site. For the moment, I'll keep it simple.
Thanks for your help.
Tony.
$world=~s/war/peace/g;
Ahem, rookie mistake
Hi,
I have been trying for sometime to replicate your results w/o success:
tail -1 /etc/shadow
bwilson:$1$j5nZfGq2$Tnn0OT.Rnvpm69.TpAucH.:13781:0:99999:7:::
perl -e 'print crypt("hahaha", "j5nZfGq2"),"\n"'
j5dTfm86E2KTw
perl -e 'print crypt("hahaha", "$1$j5nZfGq2"),"\n"'
perl -e 'print crypt("hahaha", "\$1\$j5nZfGq2"),"\n"'
$1$j5nZfGq2$Tnn0OT.Rnvpm69.TpAucH.
When I realized I'd forgotten to put the back-slashes on the "$", I decided to find some quiet corner and kick my own *ss. Hopefully, this little note will remind others not to do my stupidity.
Kudos for the excellent write-up. It has solved my problem.
Bob Wilson