#!/usr/bin/perl # File: bcrypt_2y use Crypt::Eksblowfish::Bcrypt; use Crypt::Random; $password = 'password'; $encrypted = encrypt_password($password); # from another program, a bcrypt 2y of 'password' = '$2y$10$iG2fZoSKzWUVn65cMDGL0uG8sWvy0G0G2Z/1Fll7zcBvEIOvn8qLG'; print "Plain $password is bcrypt as $encrypted\n"; if (check_password($password, $encrypted)) { print "Valid Password $password\n" } sub encrypt_password { my $password = shift; my $salt = shift || salt(); my $settings = '$2y$10$'.$salt; return Crypt::Eksblowfish::Bcrypt::bcrypt($password, $settings); } sub check_password { my ($plain_password, $hashed_password) = @_; # Regex to extract the salt if ($hashed_password =~ m!^\$2y\$10\$([A-Za-z0-9+\\\.\/]{22})!) { # Use a letter by letter match rather than a complete string match to avoid timing attacks my $match = encrypt_password($plain_password, $1); my $bad = 0; for (my $n=0; $n < length $match; $n++) { $bad++ if substr($match, $n, 1) ne substr($hashed_password, $n, 1); } return $bad == 0; } else { return 0; } } # Return a random salt sub salt { return Crypt::Eksblowfish::Bcrypt::en_base64(Crypt::Random::makerandom_octet(Length=>16)); }