Perl to PHP Conversion - Bugzilla bz_crypt
Posted: Wed Sep 21, 2011 4:16 am
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.
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;
}
}