如果攻击者想要破坏您的系统,他会尝试猜测密码。这意味着尝试潜在的密码直到一个“匹配”(这就是所谓的字典攻击)。配什么?攻击者可以通过两种方式查看密码是否正确:
- 通过验证存储的哈希值;
- 通过应用 PKCS#5 密码推导(PBKDF1 或 PBKDF2,PKCS#5 描述两者),然后解密 AES 密钥,然后使用获得的密钥尝试解密使用该密钥加密的任何内容,并查看结果是否有意义。
攻击者将采用对他来说最容易的任何方式。PBKDF* 函数包括一些使字典攻击更难的特性,即盐和可配置的内部迭代次数。迭代使每次密码试验变得昂贵。salt 可以防止攻击者使用预先计算的哈希表(例如“彩虹表”)来优化事物。PBKDF2 在这方面被认为相当出色(尽管bcrypt可以说更好)。如果您的密码验证散列不包含相同的功能,那么该散列是攻击者将使用的弱点。
简而言之,您的安全性将是您的密码验证哈希和 PKCS#5 密钥派生中较弱的安全性。
更好的方案如下:
- 根据用户密码,您可以使用适当的密钥导出函数(例如 PBKDF2 或 bcrypt)导出密钥K。这使用盐S。
- 你用K对称地加密你的“AES 密钥” ,产生一些值B。
- 您为每个用户存储h(K)、S和B (其中h是一个安全散列函数——我建议使用 SHA-256)。
要验证密码,您可以使用存储的盐S重新运行密钥派生函数,并对结果进行散列以查看它是否与存储的h(K)匹配。如果要解密B,只需使用重构的K。这样,您可以确定用于加密的密钥派生和密码验证哈希同样能够抵抗字典攻击。