我已经阅读了SO(以及我试图再次研究之后在谷歌上发现的其他网站),在数据库中存储密码的正确安全方法是存储散列+盐渍值密码。最重要的是,每个用户的盐应该是不同的,因此黑客即使拥有加密值也不会造成伤害。
我不太确定腌制的含义。根据我的理解,您对密码进行哈希处理,然后使用另一个哈希值(盐)并将这两个值组合在一起,以便检索原始密码的算法对于每个用户都是不同的。
所以基本上,我需要做的是散列密码,然后对每个用户使用不同的哈希值(即:用户名或电子邮件地址)然后我可以做一个简单的数学运算这两个值来获取编码密码。
这是正确的还是我对密码散列+腌制没有任何了解?
一个简单的解释或示例将证明是有用的,因为我发现的网站并没有完全解释密码是什么。
编辑:在阅读了目前为止留下的评论和答案之后,我明白我并不真正了解盐是什么,因为我错过了一些关键概念而且我做出了错误的假设。 / p>
我想知道的是:如果随机生成,你如何持续获得相同的盐?如果像某些人提到的那样将盐存储在数据库中,那么我可以看到你如何继续获得相同的盐,但这带来了另一个问题:如果有权访问数据库的任何人都可以访问密码,那么它如何使密码更安全盐?难道他们不能只将(已知的)盐附加到他们尝试的所有密码上,结果会比没有密码的时候一样(有些小的时间损失)吗?
答案 0 :(得分:5)
让我尝试用稍微过于简单的例子来澄清一点。 (md5()
仅用于示例目的 - 您不在实践中使用它。)
salt只是一个随机字符串,在加密之前会附加到密码上。假设你有密码letmein
,你可以像这样哈希......
echo md5('letmein')
...你会得到输出0d107d09f5bbe40cade3de5c71e9e9b7
。如果您google this,您会收到许多页面,告诉您这是letmein
的MD5哈希值。盐旨在帮助防止这类事情发生。
假设您有一个生成随机randomStringGenerator()
字符串的函数$x
。要使用它来加密密码,你可以这样做:
$password = 'letmein';
$salt = randomStringGenerator(64); //let's pretend this is 747B517C80567D86906CD28443B992209B8EC601A74A2D18E5E80070703C5F49
$hash = md5($password . $salt);
然后您将执行md5(letmein747B517C80567D86906CD28443B992209B8EC601A74A2D18E5E80070703C5F49)
,其中af7cbbc1eacf780e70344af1a4b16698
,which can't be "looked up"与letmein
一样轻松返回。
然后你将两个哈希值和盐存储起来,当用户输入密码登录时,你将重复上面的过程,看看用户输入的密码是否与存储的盐附加了哈希值与存储的哈希相同。
然而!由于MD5和SHA2等一般哈希算法速度非常快,you shouldn't use用于存储密码。查看phpass以获取bcrypt的PHP实现。
希望有所帮助!
答案 1 :(得分:2)
使用盐来避免攻击者创建彩虹表,例如包含所有(通常)密码和相应散列的表,按散列排序(或以某种方式容易访问)。如果攻击者拥有这样的表或者可以创建它,然后使用无保留的哈希值获取密码数据库,他就可以轻松查找密码,即使对于所有用户也是如此。
如果哈希被腌制(并且攻击者得到了哈希的盐),他仍然能够做同样的攻击(只需要稍微多一点的工作来输入盐) - 但现在这个建立彩虹的工作table对于使用另一个salt的下一个哈希是无用的,这意味着需要再次为每个用户完成。 仅此是盐的目标。对您的单个帐户的字典攻击仍然需要与以前相同的时间,只是彩虹表是无用的。 (要对字典攻击做一些事情,请参见下文。)
盐的使用方式取决于使用的算法。一些哈希算法(例如bcrypt,专门用于密码哈希)具有特殊的盐输入参数(或自己生成盐并将其包含在输出中):
H = bcrypt(密码,硬度)或H = bcrypt(盐,密码,硬度)
(第一个变体生成盐本身,而第二个变体从外部生成。两者都包含输出中的散列和硬度参数。)
其他需要在某些特殊模式下使用才能使用盐。 适用于大多数哈希算法的简单变体将使用HMAC,salt为“message”输入,密码为key:
HMAC(密码,盐)=哈希(密码⊕opad ||哈希(ipad⊕密码||盐))
其中opad和ipad是一些常量填充值。
然后将盐与哈希一起存储。 (对于稍高的屏障,你可以将哈希存储在除盐之外的其他位置。但是你仍然需要两个用于登录。)对于登录,你将把密码和存储的盐给你的哈希函数,并比较结果与存储的哈希。 (大多数bcrypt库都内置了“密码验证”功能,这样做。)
对于密码存储,使用慢哈希算法而不是快速算法非常重要,以避免(或确实:减慢)对密码的暴力破解或字典攻击,因为大多数人会有很短的密码。 bcrypt是一个仅为此目标而制作的算法(其缓慢可通过参数进行调整)。
如果您使用快速哈希函数,请务必经常重复它以使其再次变慢。 (但更好,真的:使用bcrypt。)
答案 2 :(得分:2)
虽然@Chris和@Pualo有很好的答案。我想再添加一些关于盐渍密码的事情。
保存密码不是真正的保护机制。如果您使用的是bcrypt或任何其他机制,则无关紧要。它只是一种拖延战术,仅此而已。
通过为每个密码使用不同的salt值,您迫使黑客为每个密码创建一个彩虹表以破解它们。这增加了它所花费的时间,但决不会使它变得不可能。请记住,使用基于云的计算,您可以启动大量计算机来创建彩虹表,您可以看到延迟非常小。
此外,大部分僵尸机都可以出租......
那就是说,你遇到麻烦的原因是为了买时间。是时候注意到您已经被破坏,修复它并告知您的用户违规行为。而已。
如果攻击者获得了足够的数据库访问权限以获取密码列表,那么几乎可以保证他们已经获得了其他所有密码。所以,到目前为止,你已经失去了一切。唯一的问题是你需要多长时间才能堵住漏洞,重置每个人的密码并告诉他们应该重置他们使用相同密码的任何其他帐户上的密码。如果你是索尼,那么这个时间显然是用几个月来衡量的,如果不是几年......;)尽量快一点。
所以,尽管这是负责任的事情,但它只是防守工具带的一部分。如果您遭到破坏,那么您可以打赌,这些用户名和密码将在不久的将来的某个地方出现在某个地方。希望在此之前你已经清理过你的房子了。
答案 3 :(得分:1)
使用salt防止预计算的彩虹表用法,例如,如果用户使用“密码”作为密码,MD5(“密码”),SHA1(“密码”)或WhatEver(“密码”)可能会很好已知结果存储在一些彩虹表中。 如果你为每个人使用不同的盐值 - 称为nonce - 你将获得MD5(HMAC(“密码”,“RandomSaltValue”)),SHA1(“密码”,“AnotherRandomSaltValue”),......这意味着两个不同对相同的初始密码进行哈希密码值。 现在关于存储这些盐值的问题......我认为它们可以存储到数据库中,盐的想法是为了防止彩虹式攻击,而不是数据库受损的问题。
答案 4 :(得分:1)
尽管bcrypt
显着降低了进程,但如果可以并行进行大量计算,攻击方案仍然可行。我知道这不太可能,这确实是一个非常资源丰富的攻击者,但让我们假设您保护的网站将包含来自Area 51的照片和文档:)在这种情况下,如果有足够的并行化,即使使用,您仍可能遇到麻烦bcrypt
。
这就是为什么我喜欢scrypt的方法 - 它不仅涉及计算成本,而且还强加了内存限制,特别是在空间方面引入成本并使这些并行攻击不可行。我只能推荐阅读该网站上链接的论文,它很好地说明了这个概念。
尽管如此,bcrypt
甚至更多scrypt
似乎在密码分析方面的关注程度低于RSA PKCS#5中概述的PBKDF2
。有关详细信息,请参阅此discussion。
答案 5 :(得分:0)
Secure hash and salt for PHP passwords怎么样?它甚至在PHP中有例子。
答案 6 :(得分:0)
首先我要说安全性很难做到,而且你真的应该依靠现有的库来尽可能地为你做。对于密码存储和验证等基本操作,这绝对是正确的。
编辑:删除了错误的信息。我会坚持我唯一的好建议,这不是自己推荐的。