in reply to encryption confusion

It is a bug in your code. If you don't pass 3 arguments to the function then you generate a salt based on the first 2 chars in $0 -> which is the script name. If the names of the scripts are different the salts will be different and thus the cryptstring will be different.

Something like this will suffice:

sub CryptPasswd { my ($username, $passwd, $salt) = @_; $salt ||= 'anystring'; # only first 2 chars will be used return crypt ($passwd, $salt); }

Note that crypt will ignore all but the first 2 chars of the salt. The two char salt is there to increase the permutations and make it harder to brute force things. Pick a secret two char string and stick with it.

cheers

tachyon

Replies are listed 'Best First'.
Re^2: encryption confusion
by gaal (Parson) on Aug 20, 2004 at 06:55 UTC
    The idea with salt, though, is that it is supposed to be generated randomly. So for better security you salt the password at creation time as some function of, say, time; and then later when you authenticate you read the user's password from the .htpasswd record, extract the salt from there, and use that to salt the current password input. This is rather better than using a single site secret for all the salts.

      I appreciate how it is done on *nix. It seemed appropriate to KISS in this case. Oh, all right I was just too lazy to offer more detail. Here is a half decent implementation that uses pseudorandom salts.....

      sub crypt_pass { my ( $pass ) = @_; my @chars = ( 'A'..'Z','a'..'z',0..9,'.','/' ); my $salt = $chars[rand(64)].$chars[rand(64)]; return crypt( $pass, $salt ); } sub check_pass { my ( $pass, $hashed ) = @_; my $salt = substr $hashed, 0, 2; # salt is first two chars of has +h string return crypt( $pass, $salt ) eq $hashed ? 1 : 0; } for(1..10) { my $crypted = crypt_pass( 'japh' ); printf "%s\t%d\t%d\n", $crypted, check_pass( 'japh', $crypted ), check_pass( '!japh', $crypted +); } __DATA__ MUNh4wMD2XmEM 1 0 3mGrf7lP7OtZc 1 0 oK7ccq5AtY1xI 1 0 .yrauX5ySsKTc 1 0 zW39UkBxi2jPo 1 0 jEzvJ.irRskvo 1 0 fz54UpRw0TZWc 1 0 a0NMpS2IufmzQ 1 0 wLjbdTPPxpwd. 1 0 WeMtUMzGuNWoc 1 0

      cheers

      tachyon

        I actually ran into a strange bug some time ago (under Apache 1.3.23) where if the salt I generated consisted of the same two characters (e.g. 'aa'), it wouldn't work under htpasswd. So here's the code I used:

        my @salt_chars = (a..z,A..Z,0-9,'.','/'); my $salt1 = $salt_chars[int(rand @salt_chars)]; my $salt2 = $salt_chars[int(rand @salt_chars)]; while ($salt2 eq $salt1) { $salt2 = $salt_chars[int(rand @salt_chars)]; } my $salt = $salt1 . $salt2;

        I'm not sure if this is still an issue; you might want to test it out on your system.

        -b

      gaal is right, but there should be an emphasis on some function of time. Since only the first two characters are used for the salt, if you just pass in time, you'll always have "10" as your salt (at least until Nov. 9 of this year, when it hits 11). One quickie way to do it is to use reverse time or even reverse rand time. If you're really paranoiod, take a look at srand or Math::TrulyRandom.

      Update: actually, big "doh" here...passing in a number as your salt only gives you 100 possible salts. tachyon's suggestion below is actually the way to do it (and they way I've done it in the past, which is why I'm kicking myself). You should still read over srand, though.

      -b

        > Since only the first two characters are used for the salt, if you just pass in time, you'll always have "10" as your salt

        Ha! talk about an unfortunate pitfall :)