所以,我发现你应该将密码与"盐"一起散列.(文章可以在这里和这里找到.)
这是代码:
$password = 'fish';
/* should be "unique" for every user? */
$salt= 'ABC09';
$site_key = 'static_site_key';
hash_hmac('sha1', $password . $salt, $site_key);
Run Code Online (Sandbox Code Playgroud)
现在我需要的方法来保存$password和$saltMySQL中,就像这样:
+---------+--------+----------+-------+
| user_id | name | password | salt |
+---------+--------+----------+-------+
| 1 | krysis | fish** | ABC09 |
+---------+--------+----------+-------+
Run Code Online (Sandbox Code Playgroud)
**fish当然会被散列,而不是以纯文本形式存储.
而我只是想知道这样做是否真的有意义,因为这样一个黑客或谁也知道盐?所以,如果他们破解密码并且看到fishABC09它们,他们会自动知道密码是fish什么?或者他可能"永远"无法破解密码,因为他不知道密码secret_key,因为它没有存储在数据库中?
如果我没有任何意义,我很抱歉.我只是一直用于sha1密码,今天我发现这些文章谈到了添加一个salt.
小智 8
关于正确存储密码的文章很好.其中一个例如:存储密码 - 完成正确!
您应该为每个用户使用不同的盐,但不需要单独存储盐.在另一个线程中查看类似的讨论
顺便说一句,你可能不应该使用sha1但是例如sha256或sha512更强的东西(至少为了避免不良宣传).对此有一个很好的答案:盐渍SHA1与盐渍SHA512相比有多不安全
$username = mysql_real_escape_string($username);
$password = mysql_real_escape_string($password);
$time = time();
$query = "
INSERT INTO user (name, unixcreationtime, passhash)
VALUES ('$username', '$time', SHA2(CONCAT('$time','$password'),512) ";
Run Code Online (Sandbox Code Playgroud)
不要使用SHA1,它不再安全.
我建议在MySQL中进行所有哈希,这样你就可以确定哈希的结果没有区别.
使用以下选择用户:
$query = "SELECT id FROM user
WHERE name = '$username'
AND passhash = SHA2(CONCAT(creationdate,'$password'),512) ";
Run Code Online (Sandbox Code Playgroud)
彩虹/字典攻击和盐渍密码 - 异端方法
密码不应存储在您的数据库中.不要推出自己的身份验证机制 - 你几乎肯定会弄错.使用Kereberos作为有价值的东西,而且我没有其他好的建议.
然而,这个问题一直在我的头骨中徘徊一段时间(见编辑),我想提出一个异端的观点.
彩虹表是所谓的,因为查找机制(链接)的使用方式 - 但它们只是字典攻击.数以百万计的字典单词和常用密码被预先散列,然后用于比较被盗的散列密码.
这适用于使用md5哈希和无盐的NT4密码进程.但是当在散列之前将盐添加到密码中时,彩虹表是无用的 - 而不是寻找"mypass"的md5散列,它必须预先计算"mypass-random-string_of-letters"
不可能猜到有人会使用什么样的盐,因此盐渍使彩虹表成为通用的,可以在任何地方使用任何服务器解决方案.
但......
这只是一个用例 - 当然是一个很大的威胁,肯定是一个防御.但盐有问题.当您想要在下次用户登录时进行身份验证时,您必须保留盐.他们发送明文(通过ssl!),将salt和hash,comapre附加到存储在数据库中的哈希.但是,如果你不保留盐密码,你不能这样做,并且错误...没有登录
但是我们不仅要防止人们绕过一张桌子来破解NT4密码.我们应该单独保护我们的用户.
盐为密码添加了双因素防御 - 即使使用哈希,攻击者也需要盐才有机会破解密码.但标准建议只是放弃了两个因素防御.可能是合理的,但我不相信.
这背后有一些数学.通常的建议(由RSA提供 - ftp.rsa.com/pub/pkcs/pkcs-5v2/pkcs5v2-0.pdf)构建一个64位的盐,用散列密码存储它.这样,您可以通过与salt重新进行重新确认密码,并且几乎不可能反转哈希值.
NB - 我在这里错了......
"接下来不可能"的位来自简单的数学.
让我们假设一个8位数的密码,有62个可能的字符(字母,大写字母和数字)
这是62 ^ 8组合,或略多于2亿万亿.
通过直接计算哈希,(即制作我的盐特定彩虹表),我应该在62 ^ 8/2之后看到一次碰撞,并且假设每秒100次哈希,这将需要大约1200万天.是的几天.
好吧,所以即使使用密码存储哈希也会使找到哈希的任务变得不可行.
但是,上面有一些假设.首先,密码是62 ^ 8范围的随机选择.在实践中,大多数密码都要弱得多 - 彩虹表并不是真正基于所有62 ^ 8种可能性 - 它们是由字典构建的,并且是多年来发现的真实密码表.
所以搜索空间,而不是62 ^ 8真的更小.多么小 ?这取决于密码"强度".
英语大约有250,000 - 750,000个单词(http://oxforddictionaries.com/page/93).让我们把500,000作为一个简单的案例.然后我们可以采用可以应用的变体 - 添加数字,添加一年,将元音转换为数字.这让我们说每个单词有3个可能的新单词,或者200万个可能的密码.
以100 /秒产生200万个哈希值可提供20,000秒或5小时 - 完全在任何笔记本电脑的范围内.
因此,如果有特定用户被定位(root,admin,spolsky等),那么使用密码立即存储salt会使破解成为可能.
将盐从密码中存储起来会增加破解的难度 - 不是以任何数学方式,只是难以获得盐和密码.可以设想一个单独的服务器,只需要明文,用户名和哈希,并查找用户加入日期使用的盐,并返回1/0
因此,简而言之,如果您使用密码存储salt并且有人访问密码,那么根据密码强度,每个密码在合理的时间内都是可破解的.每个用户使用不同的盐可以保护所有其他用户,但如果您使用的是特定帐户,则无关紧要.如果黑客只使用一个密码,那么使用密码存储盐会使裂缝成为可能.在密码表的其他地方保留一个旋转的盐意味着黑客现在需要两次数据窃取来破解密码,因为没有盐,任何攻击注定要经过数千年的工作.
这完全是一种折衷 - 迫使人们使用15位密码意味着他们都会在屏幕上注明它,或者变得"容易记住"即单词.
此时您也可以转移到Kerberos或类似的 - 如果您保护的数据很有价值,用户将理解并查看它.如果不是我们为什么要打扰.
不过我还是建议你没有实现自己的身份验证mechansim.使用Kerberos,使用半公共PKI,不要自己滚动.我不知道如何判断我的服务器是否只是将持有我的盐的RAM换成了磁盘,这只是我在编写自己的身份验证时可以立即想到的一个错误.
HTH