Argon2 encryption in perl - perl

I'm making simple perl script for sign up/login with Argon2 for encryption. (The credentials are taken from HTML Forms). The creation of users works fine , username and hashed password are stored in the database. The problem comes with the extraction/authentication. I'm not sure I'm using the verification properly.
#!/usr/bin/perl
use strict;
use warnings;
use Crypt::Argon2 qw/argon2id_pass argon2id_verify/;
use CGI::Simple;
use DBI;
sub get_data{
my ( $user) = #_;
my $statement = "SELECT USER_HASH FROM LOGIN_DATA WHERE USER_NAME = ?";
my $driver = "mysql";
my $database = "USERS";
my $dsn = "DBI:$driver:database=$database";
my $dataUsr = "user";
my $dataPass = "user123";
my $dbcon = DBI->connect($dsn,$dataUsr,$dataPass) or die $!;
my $preState = $dbcon->prepare($statement);
$preState->execute($user);
my #row ;
my $hash_pass;
while(#row=$preState->fetchrow_array()){
$hash_pass = $row[0];
}
return $hash_pass;
}
sub check_pass{
my ($user , $pass) = #_;
my $encoded = get_data($user);
return argon2id_verify($encoded , $pass);
}
my $cgi = CGI::Simple->new;
my $username = $cgi->param("username");
my $password = $cgi->param ("password");
check_pass($username , $password)
This are the erors when i try to run in in the terminal Use of uninitialized value in subroutine entry at checkUser.cgi line 30. Could not verify argon2id tag: Decoding failed at checkUser.cgi line 30.

Removing all the CGI, all the database connectivity and replacing the input with dummy values shows the same error message, so my guess is that you are not getting a result from the database:
#!/usr/bin/perl
use strict;
use warnings;
use Crypt::Argon2 qw/argon2id_pass argon2id_verify/;
sub check_pass{
my ($user , $pass) = #_;
return argon2id_verify(undef, $pass);
}
check_pass("mytest", "some-test-password-2018")
__END__
Use of uninitialized value in subroutine entry at tmp.pl line 7.
Could not verify argon2id tag: Decoding failed at tmp.pl line 7.
So the best step would be for you to isolate the problem by verifying that you actually get a result from the database.

Related

PM module in Perl Program Error :: Can't call method "prepare" on an undefined value at

I must ascertain how to eliminate the error.
$ perl use_pkg.pl
Can't call method "prepare" on an undefined value at use_pkg.pl line...
I have two files via.
First is a perl package PKG.pm
package PKG;
require 5.000;
require Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(SoxDBLogin);
use DBI;
sub SoxDBLogin
{
# these values are provided using Unix env variables
$user = $user|| $ENV{"DBUSER"};
$pswd = $pswd||$ENV{"DBPSWD"};
$srvr = $srvr||$ENV{"DBSRVR"};
$dbName = $dbName|| $ENV{"DBNAME"};
printf STDOUT ("Program %s: DBUSER <%s>, DBSRVR <%s>, DBNAME <%s>\n",$0,$user,$srvr,$dbName);
$DSN = "driver={ODBC Driver 17 for SQL Server};server=$srvr;data base=$dbName;uid=$user;pwd=$pswd";
$dbh = DBI->connect("DBI:ODBC:$DSN") or die "Couldn't open database : $DBI::errstr\n";
}
Another file has a perl program use_pkg.pl
#!/usr/bin/perl
use PKG;
use DBI;
&main;
sub main
{
&initialize;
&delFeedForDay;
}
sub initialize
{
# these values are provided using Unix env variables
$user = $ENV{"DBUSER"};
$pswd = $ENV{"DBPSWD"};
$srvr = $ENV{"DBSRVR"};
$dbName = $ENV{"DBNAME"};
&SoxDBLogin($user,$pswd,$srvr,$dbName);
}
sub delFeedForDay
{
my $sql = "SELECT count(*) FROM [myDb].[dbo].[adp_users]" ;
# I receive the error "Can't call method "prepare" on an undefined value at" on next line
my $sth = $dbh->prepare($sql) or die "Can't prepare statement: $DBI::errstr";
my $exStat = $sth->execute() or die "ERROR while query execution...exiting $DBI::errstr\n";
my $data = $sth->fetchrow();
printf STDOUT ("Data : $data \n");
$sth->finish();
}
Used return for getting the DB handle from the sub SoxDBLogin
return $dbh ;
Then simply assigned it to a variable in sub initialize
$dbh = &SoxDBLogin($user,$pswd,$srvr,$dbName);
It worked perfectly.

LDAP Search for User DN Returns a Hash - Perl

All I am trying to do is search for a user and return the user's DN in a Perl script. However, my script is printing a reference to a hash instead of the actual DN of the user.
The DN needs to be put into another variable later on so I need the DN to be right.
Here is my code:
use strict;
use warnings;
use Net::LDAPS;
use Net::LDAP;
use Config::Simple;
use Try::Tiny;
#LDAP connection.
my $ldap;
my $hostname = "Hostname";
my $port = 2389;
my $rootDN = "username";
my $password = "password";
#Connect to LDAP
$ldap = Net::LDAP->new( $hostname, port => $port ) or die $#;
#Send username and password
my $mesg = $ldap->bind(dn => $rootDN, password => $password) or die $#;
my $result = $ldap->search(
base => "ou=AllProfiles",
filter => "(cn=Alice Lee)",
attrs => ['*','entrydn'],
);
my $href = $result;
print "$href\n";
Here is my output:
Does anyone know why I am getting this? Or know how to fix it?
Thanks!
You get back a whole object which you need to get the results from, and from that, navigate to what you want. I believe this will work, if indeed "entrydn" is the correct name.
my $entries = $result->entries;
my $dn = $entries[0]->get_value('entrydn');
(If you expect to return more than one entry, of course you will have to iterate. If you may get no results, you need to check for that too.)

Using Bycrypt in Perl

#!/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.
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";
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 :)

perl DBI memory leak

I'm having some memory leak issues in a perl script that I'm running for extended periods of time, where the amount of memory that perl is taking up just continues to grow. Because of this, I am trying to use Devel::Leak to track down the leak. I discovered that whenever I call DBI's prepare method, the number of scalar values returned by Devel::Leak goes up by one. Below is I test script I've put together that does what I'm describing:
#!/usr/bin/perl
use strict;
use Devel::Leak;
use DBI;
START:
my $handle; # apparently this doesn't need to be anything at all
my $leaveCount = 0;
my $enterCount = Devel::Leak::NoteSV($handle);
print "ENTER: $enterCount SVs\n";
{
# CONFIG VARIABLES
my $platform = "mysql";
my $database = "db";
my $host = "localhost";
my $port = "3306";
my $user = "user";
my $pw = "pass";
#DATA SOURCE NAME
my $dsn = "dbi:mysql:$database:$host:3306";
# PERL DBI CONNECT
my $dbh = DBI->connect($dsn, $user, $pw);
$dbh->prepare("SELECT * FROM table"); # The script seems to gain one SV without this
# line here, but since this is my issue in my
# main script I decided to leave it in
# undef $dbh; I tried undef-ing this, but it made no difference
}
$leaveCount = Devel::Leak::CheckSV($handle);
print "\nLEAVE: $leaveCount SVs\n";
sleep(1);
goto START;
So is there something I'm doing wrong here, or is this a memory leak in the DBI module? Also, I know that adding one SV every time around the loop isn't a huge deal, and that I most likely have larger memory leaks elsewhere that are causing perl to take so much of the server's memory. However, I'd still like to fix this if I could. Coder's curiosity :)
UPDATE:
The first time through it seems to add about 3,000 SV's, and then every time after that it goes up 1 at a time.
There is a instance of DBI::dr (a blessed hash) living at $DBI::lasth. Check out the ChildHandles key.
#!/usr/bin/perl
use strict;
use warnings;
use Devel::Leak;
use Data::Dumper;
use Symbol::Table;
use DBI;
START:
{
my $handle;
my $enterCount = Devel::Leak::NoteSV($handle);
DB:
{
my $platform = "mysql";
my $database = "db";
my $host = "localhost";
my $port = "3306";
my $user = "user";
my $pw = "pass";
my $dsn = "dbi:mysql:$database:$host:3306";
my $dbh = DBI->connect( $dsn, $user, $pw );
$dbh->prepare("SELECT * FROM table");
$dbh->disconnect();
}
my $st = Symbol::Table->New( 'SCALAR', 'DBI' );
for my $subpkg ( keys %{ $st } ) {
my $val;
{
my $var = "DBI::${subpkg}";
no strict 'refs';
$val = ${$var};
}
print "scalar '$subpkg' => '$val'\n";
}
print Dumper( $DBI::lasth );
$DBI::lasth->{ChildHandles} = []; # <-- reset leaking data structure
my $leaveCount = Devel::Leak::CheckSV($handle);
print "\nCOUNT: $enterCount to $leaveCount SVs\n";
sleep(1);
redo START;
}

How to return a hash from a module perl

Ok so this question has been bothering me for some time. I'm running a module that connects to a database and returns values from a query. I have a script calling the module and attempting to return the value from the subroutine of the module. But since code is better than words here's what I have:
sub selectCustomerName ($code){
connectDB() or die "Failed in subroutine";
#Selects customer name from customer table where code is $code
my $selectName = "SELECT * FROM customers WHERE code = ?";
my $sth = $dbh->prepare($selectName);
$sth->execute($code);
my $hash = $sth->fetchrow_hashref;
$hash->{customer_name} = $name;
return $name;
$sth ->finish();
$dbh->disconnect();
}
That's my module, here's my script:
#!/usr/bin/perl
require Connect;
use warnings;
my $dbh = Connect::connectDB();
my $results = Connect::selectCustomerName('38d');
print $results;
From a lot of messing around and switching variables I've got it to print 0, and the hash reference but never the actual value of the hash. Any help would be great thanks!
There are some mistakes. Try this:
use strict; use warnings; # never forget this 2 pragmas
use Data::Dumper; # print what's inside data structures or object
sub selectCustomerName {
my $code = shift; # or my ($code) = #_;
connectDB() or die "Failed in subroutine";
#Selects customer name from customer table where code is $code
my $selectName = "SELECT * FROM customers WHERE code = ?";
my $sth = $dbh->prepare($selectName);
$sth->execute($code);
my $hash = $sth->fetchrow_hashref;
print Dumper $hash;
$name = $hash->{customer_name};
$sth ->finish();
$dbh->disconnect();
return $name;
}
if you put finish() & disconnect() after the return, they will never be invoked.
Simplest way to see what you actually have is probably to use Data::Dumper.
#!/usr/bin/perl
use strict;
use warnings;
require Connect;
use Data::Dumper;
my $dbh = Connect::connectDB();
my $results = Connect::selectCustomerName('38d');
print Dumper $results;
But if you have a hash reference then you can deference it using %{$hash_ref} and use it as you use any other hash.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
require Connect;
my $dbh = Connect::connectDB();
my $results = Connect::selectCustomerName('38d');
foreach (keys %{$results}) {
say "Key: $_, Value: $results->{$_}";
}