3
#!/usr/bin/perlml -Tw
use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser); # show errors in browser
use Authen::Passphrase::BlowfishCrypt;
use Bytes::Random::Secure;

print "Content-type:text/html\n\n";

# read the CGI params
my $cgi = CGI->new;
my $username = $cgi->param("username");
my $password = $cgi->param("password");
if ($username =~ /[^a-zA-Z0-9]/) { die "Illegal characters" };
if ($password =~ /[^a-zA-Z0-9]/) { die "Illegal characters" };

my $settings = './settings.cnf';

use DBI;
my $dsn =
  "DBI:mysql:DB;" . 
  "mysql_read_default_file=$dbsettings";    

my $dbh = DBI->connect($dsn, undef, undef,{RaiseError=>1})
                or die "Could not connect to database: $DBI::errstr";

# check the username and password in the database
my $statement = qq{SELECT username,password FROM table WHERE username=? and password=?};
my $sth = $dbh->prepare($statement)
  or die $dbh->errstr;
$sth->execute($username, $password)
  or die $sth->errstr;
my ($userID) = $sth->fetchrow_array;

# create a JSON string according to the database result
my $json = ($userID) ? 
  qq{{"success" : "login is successful", "userid" : "$userID"}} : 
  qq{{"error" : "username or password is wrong"}};

# return JSON string
print $json;

$dbh->disconnect();

I'm now trying to implement bcrypt, over here... but unable to find any good example to learn from. I am having trouble generating random salts, since the documentation on cpan is so obscure for a perl nobie like me.

I tried something like this:

my $gen = Authen::Passphrase::SaltedSHA512->new( passphrase => 'Sneaky!' );
my $salt = $gen->salt_hex;

my $hash = bcrypt_hash({
                        key_nul => 1,
                        cost => 8,
                        salt => $salt,
                }, $password);

tried to print $hash, got a "salt must be 16 octet long exactly" error

That's just me being lazy, and ignorant.. firing a arrow in the darkness. I really need a nice example, my head hurts, after 5 hours of stray thoughts and googling.

Would really appreciate the help.

PS: I have seen 2-3 very vague examples, one here in stackflow, those didn't give me any leads. Something fresh is desired.

Ahmad Bilal
  • 380
  • 1
  • 2
  • 15

2 Answers2

6

If you're already using Authen::Passphrase, you can let it do all the work for you:

use Authen::Passphrase::BlowfishCrypt;

my $password = "Sneaky!";

my $ppr = Authen::Passphrase::BlowfishCrypt->new(
    cost        => 8,
    salt_random => 1,
    passphrase  => $password,
);
my $string = $ppr->as_rfc2307;
print $string, "\n";

# Then, to verify the password
$ppr = Authen::Passphrase->from_rfc2307($string);
if ($ppr->match($password)) {
    print "OK\n";
}

If you want to work with Crypt::Eksblowfish::Bcrypt directly, note that it expects a 16-byte string as salt:

use Crypt::Eksblowfish::Bcrypt qw(bcrypt bcrypt_hash en_base64);

my $password = "Sneaky!";

my $salt = '';
for my $i (0..15) {
    $salt .= chr(rand(256));
}

my $hash = bcrypt_hash({
    key_nul => 1,
    cost    => 8,
    salt    => $salt,
}, $password);

# or

my $salt_base64 = en_base64($salt);
my $string = bcrypt($password, "\$2a\$08\$$salt_base64");
print $string, "\n";
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
  • Assuming this makes a salt, and adds it automatically to the hash, how do I compare if the password is correct or not. Btw, whats the difference between both the print commands? Also, can you point me to a good tutorial or something, (not the cpan) just so, I understand, how this really works, due to its critical nature. Many thanks for the help! – Ahmad Bilal Dec 31 '13 at 10:56
  • I added an example for how to verify the password. If you have more questions, please ask them separately. – nwellnhof Dec 31 '13 at 11:01
  • this passphrase.. do I have to substitute $password in place of it? I'm supposing thats how it works? I was confused by the term "passphrase" earlier as well, when I read CPAN. – Ahmad Bilal Dec 31 '13 at 11:10
  • btw, If I'm correct, the Crypt.. method uses the random number generator using the rand command. what does the first method(authen) one uses? – Ahmad Bilal Dec 31 '13 at 11:15
  • 1
    `Authen::Passphrase` uses [`Data::Entropy::Algorithms`](https://metacpan.org/pod/Data::Entropy::Algorithms) which defaults to Rijndael (AES) in counter mode. – nwellnhof Dec 31 '13 at 11:19
  • okay, here is my main thought right now: for testing: I would store a salted hash in the MYSQL manually. Then I would run the code again, and 'TempString= Select $salted_password from database where username=$username',.. 'if TempString = Salted Password [user authenticated]' and vice versa. I'm **assuming** that despite the salts being different to naked eye, they would match if the correct password is used only? – Ahmad Bilal Dec 31 '13 at 11:47
  • that didn't work out.. so how should I do this for MYSQL stored hashes? I updated my code in the original post to what I have right now. – Ahmad Bilal Dec 31 '13 at 12:23
  • still waiting for any help! – Ahmad Bilal Jan 01 '14 at 14:44
  • StackOverflow isn't a forum. You asked how to generate a salt for `Crypt::Eksblowfish:Bcrypt` and I gave you an answer. If you found the answer helpful, consider [accepting it](http://meta.stackexchange.com/a/5235). If you have more questions, please ask them separately. – nwellnhof Jan 01 '14 at 17:56
  • ok got it, sorry.. I didn't get your meaning earlier by "ask them separately". – Ahmad Bilal Jan 01 '14 at 19:28
0

I found part of the remaining answer here, incase anyone needs it.

Is there a perl module to validate passwords stored in "{crypt}hashedpassword" "{ssha}hashedpassword" "{md5}hashedpassword"

thanks a lot to nwellnhof for all the help :)

Community
  • 1
  • 1
Ahmad Bilal
  • 380
  • 1
  • 2
  • 15