首先,Kerckhoffs 原则始终是可取的:
一个密码系统应该是安全的,即使系统的所有内容,除了密钥,都是公共知识。
在这种情况下,密码是密钥。因此,保持密码系统的秘密不是目标。
其次,您对那些是 md5 或 sha512 哈希是错误的;存储在您的值/etc/shadow
是 md5crypt 或 sha512crypt,这涉及加强过程(多轮 md5 或 sha512 哈希)。
现在,如果您的四个选择是 MD5crypt、sha256crypt、sha512crypt 和 bcrypt(Linux 系统中最流行的选择),这里有四个散列,全部使用$saltsalt$
(或等效)作为盐和散列密码生成not my real password
:
>>> import crypt
>>> crypt.crypt('not my real password','$1$saltsalt')
'$1$saltsalt$4iXfpnrgHRXkrDbPymCE4/'
>>> crypt.crypt('not my real password','$5$saltsalt')
'$5$saltsalt$E0bMpsLR71z8LIvd6p2tD4LZ984JxyD7B9lPLhq4vY7'
>>> crypt.crypt('not my real password','$6$saltsalt')
'$6$saltsalt$KnqiStSM0GULvZdkTBbiPUhoHemQ7Q06YnvuJ0PWWZbjzx3m0RCc/hCfq54Ro3fOwaJdEAliX9igT9DD2oN1u/'
>>> import bcrypt
>>> bcrypt.hashpw('not my real password', "$2a$12$saltsaltsaltsaltsalt..")
'$2a$12$saltsaltsaltsaltsalt..FW/kWpMA84AQoIE.Qg1Tk5.FKGpxBNC'
即使没有注释,也很容易弄清楚它们各自使用哪种方案(md5crypt、sha256crypt、sha512crypt 和 bcrypt 分别长 34、55、98 和 60 个字符(在带注释和盐的 base64 编码中)。所以除非你建议截断散列,或更改散列属性注释以保持一致性不会失去任何安全性。它还为您提供了一种优雅更新用户密码的方法。如果您认为 md5crypt 不再安全,您可以将用户的散列切换为bcrypt 在下次登录时(然后在一段时间后停用所有留在 md5crypt 上的帐户)。或者如果您的算法(如 bcrypt(当时是 2 美元)需要更新,因为设计中的缺陷,您可以轻松识别有缺陷的方案当固定方案达到$ 2a $时。
更糟糕的是,您可以尝试说,我将使用新的常量和圆键修改 sha512。那会让它变得超级难打破——对吧?不,它只是让你很难知道你没有意外引入一个重大漏洞。如果他们可以访问您的 /etc/shadow,他们可能还可以访问用于登录的库,并且随着时间的推移可以对您的哈希方案进行逆向工程,这将比破解强密码简单得多。
同样,暴力破解存储在 sha256 散列中的非常强的密码短语的预期时间是 O(2^256),例如,十亿台计算机每纳秒执行十亿个 sha256crypts (每个涉及约 5000 轮 sha256),将需要 300000000000000000000000(3 x 10^23) 乘以宇宙的年龄来打破它。使用 sha512crypt,如果可观测宇宙中约 10^80 个原子中的每一个每纳秒执行 10 亿次 sha512crypt,则仍需要宇宙年龄的 10^38 倍。(这假设您拥有 256 位和 512 位或更高的熵密码)。