Perl to PHP Conversion - Bugzilla bz_crypt

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Perl to PHP Conversion - Bugzilla bz_crypt

Post by Benjamin »

I took a stab at converting some PERL code to PHP, but since I'm not familiar with PERL it didn't turn out too well. I'm trying to convert the bugzilla password validation code to PHP.

Here's the PERL and PHP, if anyone can let me know what I've done wrong I would appreciate it.

Code: Select all

sub bz_crypt {
    my ($password, $salt) = @_;

    my $algorithm;
    if (!defined $salt) {
        # If you don't use a salt, then people can create tables of
        # hashes that map to particular passwords, and then break your
        # hashing very easily if they have a large-enough table of common
        # (or even uncommon) passwords. So we generate a unique salt for
        # each password in the database, and then just prepend it to
        # the hash.
        $salt = generate_random_password(PASSWORD_SALT_LENGTH);
        $algorithm = PASSWORD_DIGEST_ALGORITHM;
    }

    # We append the algorithm used to the string. This is good because then
    # we can change the algorithm being used, in the future, without
    # disrupting the validation of existing passwords. Also, this tells
    # us if a password is using the old "crypt" method of hashing passwords,
    # because the algorithm will be missing from the string.
    if ($salt =~ /{([^}]+)}$/) {
        $algorithm = $1;
    }

    my $crypted_password;
    if (!$algorithm) {
        # Wide characters cause crypt to die
        if (Bugzilla->params->{'utf8'}) {
            utf8::encode($password) if utf8::is_utf8($password);
        }

        # Crypt the password.
        $crypted_password = crypt($password, $salt);

        # HACK: Perl has bug where returned crypted password is considered
        # tainted. See http://rt.perl.org/rt3/Public/Bug/Display.html?id=59998
        unless(tainted($password) || tainted($salt)) {
            trick_taint($crypted_password);
        }
    }
    else {
        my $hasher = Digest->new($algorithm);
        # We only want to use the first characters of the salt, no
        # matter how long of a salt we may have been passed.
        $salt = substr($salt, 0, PASSWORD_SALT_LENGTH);
        $hasher->add($password, $salt);
        $crypted_password = $salt . $hasher->b64digest . "{$algorithm}";
    }

    # Return the crypted password.
    return $crypted_password;
}

sub generate_random_password {
    my $size = shift || 10; # default to 10 chars if nothing specified
    return join("", map{ ('0'..'9','a'..'z','A'..'Z')[rand 62] } (1..$size));
}

Code: Select all

class bz_crypt {
    const
      PASSWORD_SALT_LENGTH          = 8,
      PASSWORD_DIGEST_ALGORITHM     = 'sha256';
    
    public function getHash($password, $salt = null) {
        $algorithm = null;
        
        if (is_null($salt)) {
            $salt       = $this->generateRandomPassword(self::PASSWORD_SALT_LENGTH);
            $algorithm  = self::PASSWORD_DIGEST_ALGORITHM;
        }

        if (preg_match('/{([^}]+)}$/', $salt, $matches)) {
            $algorithm = $matches[1];
        }

        if (is_null($algorithm)) {
            return crypt($password, $salt);
        } else {
            $salt = substr($salt, 0, self::PASSWORD_SALT_LENGTH);
            $hash = hash($algorithm, $salt . $password);
            return $salt . $hash . '{' . $algorithm . '}';
        }
    }

    public function generateRandomPassword($length = 10) {
        $chars = array_merge(range(0, 9), range('a', 'z'), range('A', 'Z'));
        $cnt = count($chars) - 1;
        $key = '';
        for ($i = 0; $i < $length; $i++) $key .= $chars[mt_rand(0, $cnt)];
        return $key;
    }
}
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: Perl to PHP Conversion - Bugzilla bz_crypt

Post by Benjamin »

Anyone here who can take a crack at this?
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Re: Perl to PHP Conversion - Bugzilla bz_crypt

Post by Mordred »

Ugh, I need some eyebleach now. Not sure on the entire thing, but these two pop out:
- password+salt, not salt+password
- hash is base64

So:

Code: Select all

$hash = base64_encode(hash($algorithm, $password.$salt, true));
Post Reply