关于安全性:Salt Generation和开源软件

Salt Generation and open source software

据我所知,产生盐的最佳实践是使用一些存储在源代码中的神秘公式(甚至是神奇常数)。

我正在做一个项目,我们计划作为开源发布,但问题是,有了这个源,就有了生成盐的秘密配方,因此我们的网站上可以运行彩虹表攻击。

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

思想?


因为关于盐渍哈希的问题是有规律的,而且似乎对这个主题有一些混淆,所以我扩展了这个答案。好的。

< BR>好的。什么是盐?

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

< BR>好的。为什么加盐(或播种)散列是有用的?

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

  • 加盐大大增加了预计算攻击的难度/成本(包括彩虹表)
  • salting确保相同的密码不会产生相同的哈希。这将确保您无法确定两个用户是否具有相同的密码。而且,更重要的是,您无法确定同一个人是否在不同的系统中使用相同的密码。
  • salting增加了密码的复杂性,从而大大降低了两者的有效性dictionary-birthday attacks(仅当salt与散列分开存储时,这才是真的)。
  • 适当的盐渍可以极大地增加对预计算攻击的存储需求,直到它们不再实用为止。(8个字符的区分大小写的字母数字密码,16位盐,哈希到128位的值,在没有彩虹减少的情况下,只需要200兆字节)。
  • < BR>好的。盐没有必要是秘密的。

    salt不是一个秘密密钥,而是一个salt通过使哈希函数特定于每个实例来"工作"。对于盐散列,没有一个散列函数,而是每个可能的盐值都有一个散列函数。这可以防止攻击者以低于攻击一个密码成本n倍的代价攻击n个散列密码。这就是盐的要点。"秘密salt"不是salt,它被称为"key",它意味着您不再计算哈希,而是一个消息身份验证代码(mac)。计算mac是一项棘手的工作(比简单地将一个键和一个值组合成散列函数要复杂得多),它是一个完全不同的主题。好的。

    盐对于使用它的每个实例都必须是随机的。这确保攻击者必须单独攻击每个salt散列。如果你依靠你的盐(或盐算法)是秘密的,你进入安全领域通过模糊(不会工作)。最有可能的是,你不会从盐的秘密中得到额外的安全;你只会得到温暖模糊的安全感。因此,它不是让你的系统更安全,而是让你分心于现实。好的。

    < BR>好的。那么,为什么盐必须是随机的呢?

    从技术上讲,盐应该是独一无二的。对于每个散列密码,salt的作用点是不同的。这意味着全世界。由于没有一个中央组织按需分配独特的盐,我们必须依赖下一个最好的办法,那就是随机选择一个不可预测的随机生成器,最好是在足够大的盐空间内,使碰撞不可能发生(两个实例使用相同的盐值)。好的。

    尝试从一些"可能是唯一的"数据(如用户ID)中获得salt是很有诱惑力的,但这种方案往往由于一些令人讨厌的细节而失败:好的。

  • 例如,如果您使用用户ID,一些坏人攻击不同的系统,可能只是集中他们的资源并为用户ID 1到50创建预先计算的表。用户ID在系统范围内是唯一的,但不在全球范围内。好的。

  • 同样适用于用户名:每个UNIX系统有一个"根",但世界上有许多根。一个彩虹表的"根"将是值得的努力,因为它可以应用于数百万个系统。更糟糕的是,还有许多"bob",许多人没有系统管理员培训:他们的密码可能非常弱。好的。

  • 独特性也是暂时的。有时,用户会更改密码。对于每个新密码,必须选择一个新的salt。否则,攻击者获得旧密码的散列值,而新密码的散列值可能同时尝试攻击这两个密码。好的。

  • 使用从密码学上安全的、不可预测的prng中获得的随机盐可能是一种过度杀伤力,但至少它可以证明保护您免受所有这些危害。这不是为了阻止攻击者知道一个单独的salt是什么,而是为了不给他们一个大的、胖的目标,这个目标将用于大量的潜在目标。随机选择使目标尽可能薄。好的。

    < BR>好的。综上所述:

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

    盐不会把坏密码变成好密码。它只是确保攻击者至少要为他破解的每一个错误密码支付字典攻击的代价。好的。

    < BR>有用来源:stackoverflow.com:密码哈希的非随机salt布鲁斯施耐尔:实用密码术(书)马塔萨诺保安:有彩虹桌就够了usenix.org:unix crypt自1976年开始使用saltowasp.org:为什么要加盐openwall.com:盐好的。

    免责声明:我不是安全专家。(尽管这个答案是由托马斯·波宁审查的)如果有任何安全专业人员发现错误,请评论或编辑此wiki答案。好的。好啊.


    实际上,盐只需要在每个入口都是独一无二的。即使攻击者能够计算出盐是什么,也会使彩虹表非常难以创建。这是因为salt是在散列前添加到密码中的,因此它有效地添加到彩虹表必须包含的条目总数中,以便为密码字段列出所有可能的值。


    自从Unix开始流行以来,存储密码的正确方法就是附加一个随机值(salt)并散列它。把盐放在你以后能拿到的地方,但你希望坏人不会拿到的地方。

    这有一些好的效果。首先,坏人不能只列出期望的密码,比如"password1",将它们散列到彩虹表中,然后通过密码文件查找匹配项。如果您有一个好的双字节salt,那么它们必须为每个预期的密码生成65536个值,这使得彩虹表的实用性大大降低。第二,如果你能阻止那些看你的密码文件的坏人使用salt,你就很难计算出可能的值。第三,你让坏人无法确定一个给定的人是否在不同的网站上使用相同的密码。

    为了做到这一点,您需要生成一个随机的盐。这将以统一的概率生成所需范围内的每个数字。这并不难,一个简单的线性同余随机数生成器会很好地实现。

    如果你有复杂的计算来制作盐,那你就错了。如果你是根据密码计算的,那就大错特错了。在这种情况下,您所要做的就是使哈希复杂化,而不是在功能上添加任何盐。

    任何擅长安全的人都不会依赖于隐藏算法。现代密码学是以经过广泛测试的算法为基础的,为了得到广泛测试,它们必须是众所周知的。一般来说,人们发现使用标准算法比自己滚动并希望它是好的算法更安全。不管代码是否是开源的,坏人仍然有可能分析程序的功能。


    您可以在运行时为每个记录生成一个随机的salt。例如,假设您正在数据库中存储哈希用户密码。您可以在运行时生成一个8个字符的随机字符串,其中包含小写和大写字母数字字符,将其前置到密码,散列该字符串,并将其存储在数据库中。由于有628种可能的盐,生成彩虹表(对于每种可能的盐)将是非常昂贵的;而且由于您正在为每个密码记录使用唯一的盐,即使攻击者生成了两个匹配的彩虹表,他仍然无法破解每个密码。

    您可以根据安全需要更改盐生成的参数;例如,您可以使用较长的盐,或者生成一个包含标点符号的随机字符串,以增加可能的盐的数量。


    在桌面应用程序加密数据并在远程服务器上发送数据的情况下,您如何考虑每次使用不同的salt?

    使用带有用户密码的pkcs_5,它需要一个salt来生成加密密钥,以加密数据。我知道在桌面应用程序中对salt进行硬编码(模糊化)不是一个好主意。

    如果远程服务器永远不知道用户的密码,是否可以每次使用不同的salt?如果用户在另一台计算机上使用桌面应用程序,那么如果他没有密钥(该密钥未在软件中硬编码),如何能够解密远程服务器上的数据?


    使用随机函数生成器生成salt,并将其存储在数据库中,每行生成一个salt,然后将其存储在数据库中。

    我喜欢盐是如何在Django注册中生成的。参考:http://bitback.org/ubernostrum/django registration/src/tip/registration/models.py cl-85

    1
    2
    3
    4
    salt=sha_constructor(str(random.random())).hexdigest()[:5]
    activation_key = sha_constructor(salt+user.username).hexdigest()
    return self.create(user=user,
               activation_key=activation_key)

    他使用随机数生成的sha和用户名的组合来生成哈希。

    Sha本身以坚固和牢不可破而闻名。添加多个维度来生成salt本身,使用随机数、sha和用户特定的组件,您的安全性是牢不可破的!