【问题标题】:Using Bycrypt in Perl在 Perl 中使用 Bcrypt
【发布时间】:2014-01-02 04:27:54
【问题描述】:
#!/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();

我现在正在尝试实现 bcrypt,在这里...但找不到任何好的示例来学习。我无法生成随机盐,因为 cpan 上的文档对于像我这样的 perl nobie 来说太晦涩难懂了。

我尝试过这样的事情:

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);

试图打印 $hash,得到一个“salt must be 16 octet long exactly”的错误

那只是我懒惰和无知.. 在黑暗中射箭。我真的需要一个很好的例子,经过 5 个小时的杂念和谷歌搜索,我的头很痛。

非常感谢您的帮助。

PS:我看到了 2-3 个非常模糊的示例,其中一个在 stackflow 中,这些并没有给我任何线索。需要新鲜的东西。

【问题讨论】:

    标签: perl hash salt bcrypt blowfish


    【解决方案1】:

    如果您已经在使用Authen::Passphrase,您可以让它为您完成所有工作:

    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";
    }
    

    如果您想直接使用Crypt::Eksblowfish::Bcrypt,请注意它需要一个 16 字节的字符串作为盐:

    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";
    

    【讨论】:

    • 假设这是一个盐,并自动将其添加到哈希中,我如何比较密码是否正确。顺便说一句,这两个打印命令有什么区别?另外,你能不能给我指出一个好的教程或其他东西,(不是cpan),我明白,由于它的关键性质,它是如何真正起作用的。非常感谢您的帮助!
    • 我添加了一个如何验证密码的示例。如果您还有其他问题,请单独提问。
    • 这个密码.. 我必须用 $password 代替它吗?我想这就是它的工作原理?我之前在阅读 CPAN 时也对“密码”一词感到困惑。
    • 顺便说一句,如果我是正确的,Crypt.. 方法使用 rand 命令使用随机数生成器。第一种方法(authen)使用什么?
    • Authen::Passphrase 使用 Data::Entropy::Algorithms 在计数器模式下默认为 Rijndael (AES)。
    【解决方案2】:

    我在这里找到了剩余答案的一部分,以防有人需要。

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

    非常感谢 nwellnhof 提供的所有帮助 :)

    【讨论】:

      猜你喜欢
      • 2012-05-01
      • 1970-01-01
      • 2017-11-21
      • 2019-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-05
      相关资源
      最近更新 更多