我想在我的系统中使用Bcrypt进行密码加密。但所有的例子都是这样的:
$password = $_POST['password'];
$salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
$hash = crypt($password, '$2a$12$'.$salt);
对我来说这看起来很安全,但我想知道,在每个例子中,在使用Bcrypt之前没有人使用密码。
由于独特的盐,Rainbow表不应该一次破解所有密码。但是如果黑客拿了一条记录并用该特定记录的盐创建了一张彩虹表,他应该能够破解一个弱密码。
因此,如果有人使用弱密码(比方说'foo'),在使用Bcrypt之前首先用SHA-512散列它会更安全。我对吗?或者这看起来更安全?
答案 0 :(得分:2)
实际上答案必须是不,它不会使密码在加密意义上显着增强。您可能知道,bcrypt(尽管要使用的函数名为crypt
)本身就是一个哈希函数,而不是加密函数。
在bcrypt中,您传递一个成本因子,它定义了将完成多少次迭代(通常是数百次迭代)。 减慢计算哈希值,这使得暴力攻击变得不切实际。之前使用SHA-512,只会添加一次迭代。
你对 salt 所说的是正确的,但当然如果你必须为每个密码构建一个彩虹表,你只需要蛮力,直到你找到匹配,不需要构建整个彩虹桌。
如果攻击者可以控制数据库和代码,那么额外的SHA-512将毫无帮助(只有一次迭代)。如果他只有没有代码的数据库(SQL-Injection),那么他将识别bcrypt哈希。他现在可以用bcrypt暴力破解,但由于SHA-512没有任何弱密码。这就像SHA-512哈希将成为破解的密码,因此字典是没用的。这是默默无闻的安全性,但只要代码不知道就会有效。在使用具有唯一盐的bcrypt之前,通过添加修复硬编码盐(密钥),可以更轻松地获得相同的效果。
答案 1 :(得分:1)
crypt()
是单向字符串哈希,而不是加密机制。要使用SHA-512哈希,必须使用hash()
函数。 Bcrypt需要PHP扩展。为了存储密码,你为什么要让它们可逆,而不是只是对它们进行哈希处理?这不太安全 - 如果有人拿到你的密钥和数据库,他们就拥有所有的密码,但是一张SHA512哈希表是没用的。
答案 2 :(得分:1)
Bcrypt合并盐以消除预先计算的查找表(Rainbow Table就是一个例子)。为什么攻击者会为单个记录构建彩虹表?不,在攻击盐渍密码时,攻击者只需通过他最有可能的密码的有序列表,重复哈希算法以查看它是否匹配。
他可以通过该列表工作多远取决于哈希算法执行的时间。 Bcrypt在你的例子中控制了“cost”因子-12(这没关系,但可能是我使用的最小值)。额外的SHA-512轮不会添加任何东西。您已经执行了4096次昂贵的bcrypt迭代。添加1个便宜的SHA-512迭代可以忽略不计。
如果您在列表中选择第一个密码,它将在几分之一秒内被破坏。如果您选择第十亿个密码,攻击者将不会破坏它几十年。
答案 3 :(得分:0)
bcrypt已经使用了salt,它在内部所做的事情比SHA512强大得多。在bcrypt之上添加SHA512的迭代(和/或额外的盐层)将不会给您带来明显更强的结果。如果这两个函数以错误的方式交互,那么以这种方式组合它们实际上可能会给你一个较弱的哈希函数。