盐生成和开源软件

据我了解,生成盐的最佳做法是使用存储在源代码中的一些神秘公式(甚至魔术常数)。

我正在开发一个我们计划以开源方式发布的项目,但问题在于源代码是生成盐类的秘密公式,因此也是我们网站上运行彩虹表攻击的能力。

我认为很多人在我面前都考虑过这个问题,我想知道最佳实践是什么。 在我看来,如果代码是开源的,那么根本就没有盐,因为盐可以很容易地进行反向工程。

思考?


真正的盐只需要每个条目都是独一无二的。 即使攻击者可以计算出盐的含量,也会使彩虹表非常难以制造。 这是因为盐在散列之前被添加到密码中,所以它有效地增加了彩虹表必须包含的条目的总数,以具有密码字段的所有可能值的列表。


由于关于腌制哈希的问题经常出现,并且似乎对这个问题有一些困惑,所以我扩展了这个答案。


什么是盐?

salt是随机的一组固定长度的字节,添加到散列算法的输入中。


为什么腌制(或种子)散列有用?

向散列中添加随机盐可确保相同的密码会产生许多不同的散列。 盐通常与散列函数的结果一起存储在数据库中。 腌制散列有很多原因:

  • 盐化大大增加了预计算攻击的难度/成本(包括彩虹表)
  • Salting确保相同的密码不会导致相同的散列。 这确保您不能确定两个用户是否具有相同的密码。 而且,更重要的是,您无法确定同一个人是否在不同的系统中使用相同的密码。
  • Salting会增加密码的复杂性,从而大大降低字典和生日攻击的有效性。 (只有当salt与散列分开存储时才是如此)。
  • 适当的腌制大大增加了预计算攻击的存储需求,直到它们不再实用。 (8个字符的区分大小写的字母数字密码与16位盐,哈希到128位值,将占用不到彩虹减少200埃字节以下)。

  • 盐不需要保密。

    盐不是一个秘密密钥,而是通过为每个实例设置特定的散列函数来“运作”盐。 用盐腌散列,不存在一个散列函数,但是对于每个可能的盐值都有一个散列函数。 这可以防止攻击者攻击N个散列密码的次数少于攻击一个密码成本的N倍。 这是盐的一点。
    “秘密盐”不是盐,它被称为“密钥”,这意味着你不再计算哈希,而是消息验证代码(MAC)。 计算MAC是一项棘手的业务(要比简单地将密钥和值集中在一个哈希函数中要复杂得多),它完全是一个非常不同的主题。

    对于使用它的每个实例,盐必须是随机的。 这确保了攻击者必须分别攻击每个盐渍散列。
    如果你依赖你的盐(或腌制算法)是秘密的,你进入默默无闻的安全领域(不起作用)。 最有可能的是,你没有从盐保密中获得额外的安全保障; 你只会得到温暖的模糊的安全感。 所以,不要让你的系统更安全,而是让你从现实中分心。


    那么,为什么盐必须是随机的?

    从技术上讲,盐应该是独一无二的。 对于每个哈希密码来说,盐的要点是不同的。 这意味着全世界。 由于没有中央组织根据需要分配独特的盐,所以我们必须依靠下一个最好的东西,即随机选择一个不可预测的随机生成器,最好在足够大的盐空间内使碰撞不可能发生(使用相同的两个实例盐值)。

    试图从一些“大概独一无二”的数据中推导出盐,例如用户ID,但这种方案经常因某些令人讨厌的细节而失败:

  • 例如,如果您使用用户标识 ,那么一些攻击不同系统的坏人可能会合并他们的资源并为用户标识1至50创建预先计算的表。用户标识是系统范围内唯一的,但不是全球范围内的。

  • 这同样适用于用户名 :每个Unix系统有一个“root”,但世界上有很多根。 “根”的彩虹表是值得的,因为它可以应用于数百万个系统。 更糟糕的是,那里还有很多“bob”,许多没有系统管理员培训:他们的密码可能很弱。

  • 唯一性也是暂时的。 有时,用户更改密码。 对于每个新密码 ,都必须选择新的盐 。 否则,攻击者获得旧密码的哈希值,新的哈希值可能会尝试同时攻击这两个密码。

  • 使用从密码安全,不可预知的PRNG获得的随机盐可能会有些过火,但至少它可以保护你免受所有这些危害。 这不是为了防止攻击者知道个人的盐是什么,而是为了不给他们一个庞大的,胖的目标,将用于大量的潜在目标。 随机选择使得目标尽可能地薄。


    结论是:

    使用随机均匀分布的高熵盐。 每当您创建新密码或更改密码时,请使用新盐。 将salt与散列密码一起存储。 赞成大盐(至少10个字节,最好16个或更多)。

    盐不会将错误的密码转换为好的密码。 它只是确保攻击者至少会为他破解的每个密码支付字典攻击价格。


    有用的来源:
    stackoverflow.com:密码哈希的非随机盐
    布鲁斯·施奈尔:实用密码学(书)
    Matasano安全:足够与彩虹桌
    usenix.org:自1976年以来,Unix crypt使用salt
    owasp.org:为什么加入盐
    openwall.com:盐

    免责声明:
    我不是安全专家。 (虽然这个答案由Thomas Pornin审查)
    如果有任何安全专家发现有问题,请发表评论或编辑此维基答案。


    由于Unix流行起来,存储密码的正确方法是添加一个随机值(salt)并对其进行散列。 以后可以将盐放在远处,但希望坏人不会得到它。

    这有一些很好的效果。 首先,坏人不能仅仅列出像“Password1”这样的预期密码,将它们拼凑成彩虹表,然后通过密码文件查找匹配项。 如果你有一个好的双字节盐,他们必须为每个期望的密码生成65,536个值,这使得彩虹表的实用性降低很多。 其次,如果你可以保留那些正在查看你的密码文件的坏人的盐,那么你就很难计算出可能的值。 第三,你已经让坏人无法确定某个人是否在不同的网站上使用相同的密码。

    为了做到这一点,你生成一个随机盐。 这应该以一致的概率产生期望范围内的每个数字。 这并不难; 一个简单的线性同余随机数发生器将会很好地工作。

    如果你有复杂的计算来制造盐,你做错了。 如果你根据密码进行计算,你会这样做。 在这种情况下,你所做的只是使散列复杂化,而不是功能上添加任何盐。

    没有人擅长安全性会依靠隐藏算法。 现代密码学基于经过广泛测试的算法,为了进行广泛的测试,它们必须是众所周知的。 一般来说,使用标准算法比单独使用标准算法更安全,并且希望它是好的。 不管代码是否是开源的,对于坏人来说,分析程序的功能往往是可能的。

    链接地址: http://www.djcxy.com/p/21543.html

    上一篇: Salt Generation and open source software

    下一篇: Client Side MD5 Hash with Time Salt