【问题标题】:How to decrypt hash stored by bcrypt如何解密 bcrypt 存储的哈希
【发布时间】:2013-08-07 17:17:22
【问题描述】:

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

#!/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));
}

【问题讨论】:

  • 这正是散列的含义。您应该永远无法读取密码。
  • 您不能“解密”哈希,因为它没有加密。哈希就像汉堡包。容易走牛->汉堡。但是你想要汉堡包->牛。祝你好运...
  • 哦,好的,我明白了,谢谢!对不起,我很困惑。
  • @MarcB 喜欢这个类比,以后会用到。
  • 使用 Authen::Passphrase 而不是拼凑您自己的身份验证方案。在stackoverflow.com/questions/3675917/…中查看我的代码

标签: perl bcrypt


【解决方案1】:

也许你搜索这个? 例如,在我的例子中,我使用 Symfony 4.4 (PHP)。 如果要更新用户,则需要输入用户密码 加密并使用当前密码进行测试 未加密以验证 如果是同一个用户。

例如:

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 doesn\'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 is not valid', null);
         }

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

【讨论】:

  • 回答问题时,谈论代码做什么很重要。纯代码的答案可能很难理解。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    你不能解密,但你可以BRUTEFORCE它......

    IE:迭代一个密码列表并检查其中一个是否与存储的哈希匹配。

    来自 github 的脚本:https://github.com/BREAKTEAM/Debcrypt

    【讨论】:

      【解决方案4】:

      要回答原始发帖人的问题....要“解密”密码,您必须像密码破解者那样做。

      换句话说,您将运行一个程序来读取大量潜在密码(密码字典),然后使用 bcrypt 以及您尝试的密码的盐分和复杂性对每个密码进行哈希处理破译。如果你很幸运,你会找到匹配的,但如果密码是强密码,那么你很可能找不到匹配的。

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

      bcrypt 哈希和加盐的速度很慢,这使得它即使在今天也成为密码存储的好选择。话虽如此,我相信NIST 推荐使用 PBKDF2 进行密码散列。

      【讨论】:

        【解决方案5】:

        你根本做不到

        bcrypt用salting,不同轮次,我一般用10次。

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

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

        【讨论】:

          【解决方案6】:

          你是在散列,而不是在加密!

          有什么区别?

          不同之处在于散列是单向函数,而加密是双向函数。

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

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

          您应该对密码进行散列还是加密?

          您现在所做的——对密码进行哈希处理——是正确的。如果您只是简单地对密码进行加密,那么违反应用程序的安全性可能会使恶意用户轻松获悉所有用户密码。如果你散列(或更好,salt and hash)密码,用户需要破解密码(这在bcrypt 上的计算量很大)才能获得该知识。

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

          【讨论】:

          • 如何检查输入的密码是否与数据库中存储的密码相同?
          • @BluGeni bcrypt 将多对一映射,因此如果用户输入密码,只需通过存储密码时使用的相同功能运行它 (encrypt_password($input))。如果输出相同,则用户probably输入了相同的密码。
          • 那么在这种情况下我需要将盐保存在数据库中吗?这不会破坏吃盐的目的吗?因为现在我每次运行脚本 $bigtest 加密都会因为我相信的随机盐而不同?
          • @BluGeni 是的,您需要将盐保存在数据库中,不,它不会破坏拥有盐的目的。每个密码的盐是不同的。这可以防止黑客获取(或生成)每个 1-8 位密码的校验和表,并从 ONE 操作中了解 40% 的用户登录信息。相反,他必须每个密码生成一次此表。
          • 那么,过去(6 年前)的亲爱的人们,以上信息仍然是处理要存储在数据库中的密码的好方法吗?这个终于破解了吗?我之所以这么问,是因为我的一位用户遭遇了数据泄露,泄露了他们的“bcrypted”密码。这是否意味着现在窃贼有了密码,仍然可以安全地假设他们很可能无法破译加密的密码吗?我确实理解理论上需要继续更改任何被破坏的密码,但我问的是用户是否没有更改密码。谢谢!
          猜你喜欢
          • 2011-11-13
          • 1970-01-01
          • 1970-01-01
          • 2020-11-18
          • 1970-01-01
          • 2015-10-07
          • 2021-11-25
          • 2012-07-09
          • 2019-11-11
          相关资源
          最近更新 更多