如何解密bcrypt存储的哈希值

时间:2013-08-06 15:39:37

标签: perl bcrypt

我有这个加密密码的脚本,但我不知道如何反转它并解密它。这可能是一个非常简单的答案,但我不明白该怎么做。

#!/usr/bin/perl
use Crypt::Eksblowfish::Bcrypt;
use Crypt::Random;

$password = 'bigtest';
$encrypted = encrypt_password($password);
print "$password is encrypted as $encrypted\n";

print "Yes the password is $password\n" if check_password($password, $encrypted);
print "No the password is not smalltest\n" if !check_password('smalltest', $encrypted);

# Encrypt a password 
sub encrypt_password {
    my $password = shift;

    # Generate a salt if one is not passed
    my $salt = shift || salt(); 

    # Set the cost to 8 and append a NUL
    my $settings = '$2a$08$'.$salt;

    # Encrypt it
    return Crypt::Eksblowfish::Bcrypt::bcrypt($password, $settings);
}

# Check if the passwords match
sub check_password {
    my ($plain_password, $hashed_password) = @_;

    # Regex to extract the salt
    if ($hashed_password =~ m!^\$2a\$\d{2}\$([A-Za-z0-9+\\.]{22})!) {
        return encrypt_password($plain_password, $1) eq $hashed_password;
    } else {
        return 0;
    }
}

# Return a random salt
sub salt {
    return Crypt::Eksblowfish::Bcrypt::en_base64(Crypt::Random::makerandom_octet(Length=>16));
}

6 个答案:

答案 0 :(得分:93)

你是HASHING,而不是加密!

有什么区别?

不同之处在于散列是一种单向函数,其中加密是双向函数。

那么,您如何确定密码是否正确?

因此,当用户提交密码时,您不会解密存储的哈希值,而是对用户输入执行相同的bcrypt操作并比较哈希值。如果它们相同,则接受身份验证。

您应该对密码进行哈希或加密吗?

您现在正在做的事情 - 散列密码 - 是正确的。如果您只是简单地加密密码,则违反应用程序安全性可能会使恶意用户轻易学会所有用户密码。如果您使用哈希(或更好的salt and hash)密码,用户需要破解密码(bcrypt上的计算成本很高)才能获得该知识。

由于您的用户可能在多个地方使用他们的密码,这将有助于保护他们。

答案 1 :(得分:2)

您根本不能

bcrypt使用不同轮次加盐,通常使用10次。

bcrypt.hash(req.body.password,10,function(error,response){ }

这10个随机字符串将添加到您的密码中。

答案 2 :(得分:1)

要回答原始发帖人的问题...。要“解密”密码,您必须执行密码破解者会做的事情。

换句话说,您运行了一个程序以从大量潜在的密码(密码字典)中进行读取,然后使用bcrypt对每个密码进行哈希处理,并从密码中提取出盐和复杂性重新尝试解密。如果幸运的话,您会找到一个匹配项,但是如果密码很安全,那么您很可能找不到匹配项。

Bcrypt具有作为慢速哈希的附加安全特性。如果您的密码已使用md5(很糟糕的选择)进行了哈希处理,那么您每秒可以检查数十亿个密码,但是由于使用bcrypt进行了哈希处理,因此您每秒可以检查的次数少得多。

bcrypt散列和加盐速度慢的事实使它成为当今存储密码的理想选择。话虽如此,我相信NIST建议使用 PBKDF2 进行密码哈希处理。

答案 3 :(得分:0)

# Maybe you search this ??
For example in my case I use Symfony 4.4 (PHP).
If you want to update User, you need to insert the User password 
encrypted and test with the current Password not encrypted to verify 
if it's the same User. 

For example :

public function updateUser(Request $req)
      {
         $entityManager = $this->getDoctrine()->getManager();
         $repository = $entityManager->getRepository(User::class);
         $user = $repository->find($req->get(id)); /// get User from your DB

         if($user == null){
            throw  $this->createNotFoundException('User don't exist!!', $user);
         }
         $password_old_encrypted = $user->getPassword();//in your DB is always encrypted.
         $passwordToUpdate = $req->get('password'); // not encrypted yet from request.

         $passwordToUpdateEncrypted = password_hash($passwordToUpdate , PASSWORD_DEFAULT);

          ////////////VERIFY IF IT'S THE SAME PASSWORD
         $isPass = password_verify($passwordToUpdateEncrypted , $password_old_encrypted );

         if($isPass === false){ // failure
            throw  $this->createNotFoundException('Your password it's not verify', null);
         }

        return $isPass; //// true!! it's the same password !!!

      }

答案 4 :(得分:0)

您无法解密,但可以对其进行暴力破解...

IE:重复访问密码列表,并检查其中一个是否与存储的哈希匹配。

github上的

脚本:https://github.com/BREAKTEAM/Debcrypt

答案 5 :(得分:0)

您可以在 PHP 中使用 password_verify 函数。它验证密码与哈希匹配

password_verify ( string $password , string $hash ) : bool

更多详情:https://www.php.net/manual/en/function.password-verify.php