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

I'm working on migrating a .htaccess password file from base64 to md5. I am re-storing all the passwords in md5 format using the htdigest command. However, the server has may scripts that are used to verify the passwords contained in the file (mostly using the pack function). I now need to write something to encode a password from an html form in md5. I've initially tried Digest::MD5
use strict; use Digest::MD5; my $md5 = Digest::MD5->new(); $md5->add('mypass'); my $digest = $md5->hexdigest; print $digest, "\n"; print "977f6d9e19594bd58e68030e029cbb3c\n";
This doesn't seem to work quite right. The results are:
a029d0df84eb5549c641e04a9ef389e5 977f6d9e19594bd58e68030e029cbb3c
The output from htdigest and Digest::MD5 don't quite match. I have considered making a system call to htdigest and parsing the results, but would prefer to use a perl routine. Can someone offer any help? Thanks.

Replies are listed 'Best First'.
Re: Digest::MD5 question
by GrandFather (Saint) on Jun 08, 2006 at 19:13 UTC

    Are you absolutly sure you are digesting exactly the same sequence of characters, including line end characters? One way to check would be to create a test file using a Perl script then digest it with both systems and check that result:

    use strict; use Digest::MD5; open OUTFILE, '<', 'temp'; print OUTFILE <<TEXT; It doesn't matter what the text is it should getthe same treatment from both digests TEXT close OUTFILE; my $md5 = Digest::MD5->new(); $md5->add('TEXT'); my $digest = $md5->hexdigest; print "Perl: $digest\n"; `systemmd5util temp > temp.out`; print "System: "; local @ARGV = ('temp.out'); print while (<>);

    Untested code.


    DWIM is Perl's answer to Gödel
Re: Digest::MD5 question
by Thelonius (Priest) on Jun 08, 2006 at 23:41 UTC
    use Digest::MD5 'md5_hex'; my ($user, $domain, $password) = @ARGV; my $digest = md5_hex("$user:$domain:$password"); print "Digest = $digest\n";
    You need to include the username, domain, and password, in that order, separated by colons.

    If the digest were just of the password, someone could create digests of all dictionary words and use them to find out the passwords of all users at the same time. By including the user name, you have to do the dictionary attack separately for each user.

    Including the domain helps to protect users who have passwords on several systems, or generic user names like "root", "apache", etc.

Re: Digest::MD5 question
by dsheroh (Monsignor) on Jun 08, 2006 at 19:31 UTC
    I've encountered similar issues before and it's usually ended up being that one version included a newline and the other didn't.
Re: Digest::MD5 question
by graff (Chancellor) on Jun 08, 2006 at 22:51 UTC
    ... $md5->add('mypass'); ... This doesn't seem to work quite right. The results are: a029d0df84eb5549c641e04a9ef389e5 977f6d9e19594bd58e68030e029cbb3c

    In what way is the latter md5 sig ("977...") supposed to be relevant? The initial sig looks like the right one if the input string is just "mypass". When I do this on a unix box:

    perl -e 'print "mypass"' | /sbin/md5
    I get the same thing you got from Digest::MD5:
    a029d0df84eb5549c641e04a9ef389e5