GX博客

分享个人 Full-Stack JavaScript 项目开发经验

静态密码安全的相关概念

静态密码是指储存在服务器中的密码数据。我们应该考虑在数据库被攻破的最坏情况下,如何保障用户密码的安全性。本文主要介绍关于此问题的相关概念。


密码熵

密码熵(密码中信息的比特数)用于衡量密码的不可预知程度。通常,至少36.86比特的密码才算是好密码。

对于随机选择的密码,广为接受的熵计算公式是 H = log(b^l)/log(2)。其中 H 为密码熵,b 为字符集的符号数量,l 为密码长度。使用 javaScript 表示即为:

let H = Math.log(Math.pow(b,l))/Math.log(2);

对于人为选择的密码熵计算方法不一(各有缺陷),下面介绍在NIST 特刊 800-63-2章节 User Selected Passwords 中计算人为选定的密码熵规则:

  • 第1个字符的熵为4比特。
  • 第2~8个字符,每个2比特。
  • 第9~20个字符,每个1.5比特。
  • 第21个及之后的字符,每个1比特。
  • 如果密码要求必须有大写字母我字母数字之外的字符,外加6比特。
  • 对于长度为1~19的密码,如果确保密码不在大型字典中,外加6比特。对于长度为20及以上的密码,认为用户肯定包含多个字典单词,故不加6比特。

加盐

对于人为选择的密码,通常会简短、容易猜测。如果直接取其哈希值,会容易受到如字典攻击和彩虹表攻击等威胁。加盐就是为了计算密码哈希值时加强数据。

盐值是一种随机数据,它的长度一般应该与哈希函数输出长度一致。PBKDF2 标准建议至少使用8字节长度的盐值。加盐后,即使相同的密码也可以得出不同的哈希值。足够长的盐值可以确保哈希值是唯一的。

hash(salt + password) = password hash

通过使用合适长度而且唯一的盐值,并且哈希函数迭代适当的次数可以放慢破解速度。


撒胡椒

与盐值不一样,胡椒值通常是一个字符串或者在一组字符串中随机选取一个。它不如哈希值一起存储,视为私钥使用。

hash(salt + pepper + password) = password hash

目前哈希算法不接受胡椒值为参数,所以这也是胡椒引人争议的原因之一。


密钥延伸

为了防范暴力攻击等媒介,需要使用密钥延伸。它把弱密码变成特别复杂的长密码。而对于哈希函数来说,不断循环迭代,直到得到所需长度和复杂度的哈希值就是密钥延伸的体现。


适合加密密码的算法

如果密码哈希值被窃取后,我们希望攻击者破解的速度越慢越好。所以对于密码加密算法,应该选择慢速度的、耗费硬件资源的更为合适。PBKDF2、bcrypt 和 scrypt 就是比较合适的密码加密算法。下面简单介绍它们的特点。

PBKDF2

  • 应用一个伪随机函数,并加盐,重复迭代,且这个迭代次数是可选择的。
  • 它已被美国政府标准化。

bcrypt

  • 专门为密码存储而设计的算法,故意放慢速度。
  • 具有适应能力。随着攻击者计算能力的提高,我们可以增加生成盐的迭代次数,不断放慢速度,抵抗暴力攻击。

scrypt

  • 不仅计算所需时间长,而且占用的内存也多。

版权声明:

本文为博主原创文章,若需转载,须注明出处,添加原文链接。

https://leeguangxing.cn/blog_post_51.html