http://www.perlmonks.org?node_id=122351

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I need to veryify a UNIX user from a webpage. I am trying to compare the encrypted password entry in the password file with the one submitted on the webpage. I can never get a match, however. I'm using the standard encryption function:

sub encrypt { @saltset = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '.', '/'); $pass = $_[0]; $now = time; ($pert1, $pert2) = unpack("C2", "$username"); $week = $now / (60*60*24*7) + $pert1 + $pert2; $nsalt = $saltset[$week % 64] . $saltset[$now % 64]; $cryptpass = crypt($pass,$nsalt); return $cryptpass; }

However, this function uses the time to set the salt. So my question is, since this function will return a different encrypted password every time, how do I authenticate a user?

Replies are listed 'Best First'.
Re: UNIX user authentication
by trantor (Chaplain) on Oct 31, 2001 at 19:33 UTC

    If I understood your question well, you simply read the encrypted password back and use the first two characters as the salt for encrypting the password you've just read.

    Then you compare them, if they match, the password is correct. Bummer otherwise.

    Warning: the salt is there because it gives 4096 different ways to encrypt the same password, so it makes it lengthy to try a dictionary attack with pre-encrypted passwords. If (as it in your case) the salt is easily predictable, somebody might find it easier to try a dictionary attack on your encrypted password, for exampl. This of course if they know how you generate salts and if tehy manage to access your encrypted data.

    As a rule of thumb, it's much better to generate it from random numbers.

    Have a look at this thread, or try a Super Search for more information.

Re: UNIX user authentication
by davis (Vicar) on Oct 31, 2001 at 20:00 UTC
    There's a module called Authen::PAM which can authenticate users against a PAM system (most modern unices have this)
    This is indepent of the contents of the passwd file, and shadow passwd files (if used). Remember to use getpwnam($user) to put a lower limit on the uid of the logins allowed.

    Hope that helps.
Re: UNIX user authentication
by fokat (Deacon) on Oct 31, 2001 at 21:09 UTC
    crypt() is smart enough to know about getting the salt out of the crypted password.

    You can try something along these lines:

    ... my $pass = (getpwnam($login))[1]; if (crypt($password, $pass) eq $pass) { ## The user supplied the correct password } else { ## The user supplied a wrong password } ...
    Which I think is considerably simpler and more portable. The code snippet you supplied will not work when the crypt() function in your system does not use a DES-based transformation.

    If you need support for other crypt() methods (MD5 or Apache), I suggest you take a look at Crypt::Passwd*

    Good luck.

Re: UNIX user authentication
by claree0 (Hermit) on Oct 31, 2001 at 19:34 UTC

    My approach would be to take the salt from the encrypted entry in the password file, and use that to hash the input password. Then you will get the same output for the same input.