time() 是一个好的盐吗?
我正在查看一些我自己没有编写的代码。该代码尝试使用 SHA512 对密码进行哈希处理,并仅使用 time()
作为盐。 time()
对于这个来说是太简单了还是这个代码安全?
感谢您的回答和评论。我在这里为新读者总结一下:
- 每个用户的盐应该不同,因此如果2个用户同时注册,他们的盐将不会是唯一的。这是一个问题,但不是一个大问题。
- 但盐不应该与用户有任何关系,所以 time() 不是一个好的盐。
- “使用随机、均匀分布、高熵盐。”——这太拗口了,那么什么代码可能生成
随机、均匀分布、高熵
盐呢?
好的,那么我用 32 个字符长的随机字符串替换 time() 怎么样?随机字符串可以通过对一组字母字符循环 32 次来生成。听起来不错吗?
I'm looking at some code that I have not written myself. The code tries to hash a password with SHA512 and uses just time()
as the salt. Is time()
too simple a salt for this or is this code safe?
Thanks for the answers and comments. I will sum it up here for the new readers:
- salt should be different for each user, so if 2 users register at the same time, their salts won't be unique. This is a problem, but not a big one.
- but salt shouldn't be in any way related to the user, so time() is not a good salt.
- "Use a random, evenly distributed, high entropy salt." -- That's a mouthful, so what code could possibly generate a
random, evenly distributed, high entropy
salt?
Ok, so how about I replace time() with a random string 32 char long. The random string could be generated from looping 32 times over a set of alphabet chars. Does that sound good?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
简短回答:
不,
time()
不是一个好的盐。长答案:
从我对 Salt Generation 的回答中复制和开源软件
至于什么似乎是随机盐的良好来源
另请阅读:什么是随机数生成最安全的种子?
在没有专用的、基于硬件的随机生成器的情况下,获取随机数据的最佳方法是询问操作系统(在 Linux 上,这称为
/dev/random
或/dev/ urandom
[两者都有优点和问题,选择你的毒药];在 Windows 上,调用CryptGenRandom()
)如果由于某种原因您无法访问上述随机源,请在PHP 你可以使用以下函数:
来自phpass v0.3
Short answer:
No,
time()
is not a good salt.Long answer:
copied from my answer to Salt Generation and open source software
As for what seems to be a good source for your random salt
Also read: What is the most secure seed for random number generation?
In the absence of dedicated, hardware based, random generators, the best way of obtaining random data is to ask the operating system (on Linux, this is called
/dev/random
or/dev/urandom
[both have advantages and problems, choose your poison]; on Windows, callCryptGenRandom()
)If for some reason you do not have access to the above mentioned sources of random, in PHP you could use the following function:
From the source of phpass v0.3
已更新
这不是一种真正好的盐,但可能足以击败除了最坚定和最足智多谋的攻击者之外的所有攻击者。好的盐的要求是:
time()
值实际上不够长,因为它们有 10 个字符,但只有数字。此外,有时两个用户在同一秒内创建时可能会获得相同的值。但只有当您遇到同一秒内自动创建许多用户的情况时,这才会成为问题。
无论如何,比完美的盐更重要的是使用良好的哈希函数,而 SHA512 是我们目前可用的最好的哈希函数之一。
Updated
It's not a really good salt, but probably good enough to defeat all but the most determined and resourceful attackers. The requirements for a good salt are:
time()
values are not really long enough, since they have 10 characters, but only digits.Also, sometimes two users may get the same value when they are created within the same second. But that's only a problem if you have situations where many users are automatically created within the same second.
In any case, far more important than a perfect salt is using a good hash function, and SHA512 is one of the best we have available right now.
这篇文章可能与您最初的问题有点偏离,但我希望您发现它有用;
安全就是要设置壁垒和障碍;纵深防守。没有真正安全的哈希解决方案,只有难以破解的解决方案。这就像在你的房子里安装防盗警报器和窗锁 - 让你的网站比其他人的网站更难被侵入。
加密算法的加盐只是安全问题的一小部分。单一盐仅仅意味着在尝试破解多个用户的密码时少了一件需要弄清楚的事情。低熵盐(例如服务器的时间)使其变得更难,而高熵盐则使其更难。使用其中哪一个,以及是否需要担心,主要取决于您所保护的数据的敏感性,以及您采取的其他安全措施。一个只提供选定城市的个性化天气预报的网站显然比包含您的家庭住址、母亲的婚前姓名、出生日期和其他可用于识别目的的信息的网站的敏感数据要少。
所以这就是问题所在;如果容易获得,高熵盐仍然是不好的盐。
在现实世界中,将盐存储在数据库中(随机或非随机)可能不如使用恒定盐并将其隐藏在无法通过网络浏览器访问的文件中,远离私人视线。虽然独特且高熵的盐很难猜测,但如果您允许从 MySql 上的任何服务器进行 root 登录并将密码设置为“password”,那么这并不重要!对比一下破解数据库与获得服务器的有效登录有多容易——这可能更难以离散地进行,因为您可以根据您的设置放置fail2ban和大量其他攻击向量观察程序。
您可以通过在数据库中存储包含用户特定盐的文件的位置(而不是盐本身)来组合这两种方法。是否需要同时破解文件系统和数据库取决于您尝试保护的数据的敏感性是否需要这种开销。
安全专家的另一种建议是将用户名存储在与密码不同的数据库(最好采用不同的技术)中,并使用 UUID 在两者之间进行引用。例如,同时使用 MySQL 和 SQLite。这意味着两个数据库都必须被破解(这也是为什么,为了举例而进入一个单独的兔子洞,您不应该将用户详细信息和信用卡号码存储在同一个数据库中,因为如果没有这些数据库就没有任何用处)另一个)。
请注意,SHA-512 和 Blowfish 等算法可以将盐作为其哈希的一部分返回。小心这些,就好像你存储了泄露算法的完整哈希值一样,这意味着黑客需要弄清楚的事情少了两件事(盐也泄露了算法)。
确保使用强密码和用户名,这样字典攻击就会失败;我知道 MD5 用户名/密码条目的所有 6 个字母数字组合的字典,并且我怀疑对于各种算法来说,还有更多可用的字典。随着低成本云和 CPGPU 计算的爆炸式增长,可用词典的大小和复杂性将呈爆炸式增长。
最终,最安全的方法永远不是以编程方式生成盐,而是要求用户通过 SSL 链接输入它以及用户名和密码(因此无法被窥探),但永远不要存储它。这是信用卡公司采取的方法;即信用卡上的 3 位 CSV 安全密钥,每次在线购买时都必须输入该密钥,因为它永远不应该存储在任何数据库中。如果您确实想生成盐,请将其单独发送给他们(例如通过短信或电子邮件),并仍然让他们每次手动输入。使用这种方法,虽然更安全,但您需要将复杂性与用户是否会停止使用该网站进行对比,因为您让他们很难被它打扰。
上述所有内容仍然依赖于这样一个事实:您还拥有针对会话劫持、跨站点脚本编写等的保护措施。如果我需要做的只是计算有效的 PHPSESSID,那么世界上最强的密码算法是无关紧要的。登录用户并劫持它!
我不是安全专家,但已尽可能多地阅读了这方面的内容。事实上,关于这个主题的书籍如此之多,这表明你的问题的答案到底有多大。
您可能想尝试的几本非常棒的书,我发现它们非常有价值:
Web 应用程序漏洞检测、利用、预防 - ISBN-13:978-1-59749-209-6
使用 Apache 防止 Web 攻击 - ISBN-13:978-0-321-32128-2
This post may veer a little too far away from your original question, but I hope you find it useful;
Security is about raising barriers and hurdles; defence in depth. There is no truly secure hashing solution, just ones that are hard to break. It's like putting in a burglar alarm and window locks in your house - make your site less attractive to break into than someone else's.
Salt for a crypt algorithm is only a small part of the security problem. A single salt simply means that there is one less thing to figure out when trying to break the password for multiple users. A low-entropy salt (such as the server's time) makes it a little bit harder, and a high-entropy salt makes it harder still. Which of these to use, and whether it's something you need to worry about primarily depends upon both the sensitivity of the data you're protecting, but also what other security measures you have in place. A site that just gives a personalised weather forecast for a selected city obviously has less sensitive data than one which has your home address, mother's maiden name, date of birth and other info which could be used for identification purposes.
So here's the rub; a high entropy salt is still a bad salt if it's easily obtainable.
In the real world, storing a salt in the database (random or not) is probably less secure than using a constant salt and burying it away from private eyes in a file inaccessible via the web browser. Whilst a unique and high entropy salt is harder to guess, if you've allowed root login from any server on MySql and set the password to 'password' it doesn't really matter! Constrast how easy it is to crack the database versus getting a valid login to your server - which is possibly more difficult to do discretely as you can put fail2ban and a plethora of other attack vector watchers in place depending upon your setup.
You can combine the two approaches by storing the location of a file containing a user-specific salt in the database, rather than the salt itself. Whether having to crack both the file system and the database is warranted depends whether the sensitivity of the data you are trying to protect warrants this overhead.
Another, alternative, recommendation from security experts is to store the username in a separate database (and ideally different technology) to the password, and reference between the two using a UUID. E.g. use both MySQL and SQLite. This means that both databases have to be cracked (and is also why, to go down a separate rabbit hole for the sake of an example, you should not store user details and credit card numbers in the same database since one is of no use without the other).
Note that Algorithms like SHA-512 and Blowfish can return the salt as part of their hash. Be careful with these as if you store the complete hash you give away the algorithm, which means there's two less thing for the hackers to figure out (the salt also gives away the algorithm).
Make sure you enforce strong passwords and usernames, so dictionary attacks will fail; I know of dictionaries for all 6-alphanumeric combinations of username/ password entries for MD5 and I suspect that there are more than this available for all sorts of algorithms. With the explosion of low-cost cloud and CPGPU computing, the size and complexity of available dictionaries is going to explode.
Ultimately, the most secure way is never to programatically generate a salt but require a user to enter it along with their username and password over a SSL link (so can't be snooped), but never store it. This is the approach taken by credit card companies; i.e. the 3-digit CSV security key on your credit card which you have to enter each and every time you buy online, since it should never be stored in any database. If you really want to generate the salt, send it to them separately (e.g. via SMS message or Email) and still make them enter it manually each time. With this approach, although more secure, you need to contrast the complexity against whether users will just stop using the site as you've made it too difficult for them to be bothered with it.
All of the above still relies on the fact that you also have protection in place against session hijacking, cross-site scripting, etc., etc. The world's strongest password algorithm is irrelevant if all I need to do is to calculate a valid PHPSESSID for a logged-in user and hijack it!
I am not a security expert, but have read up on this as much as I reasonably can do. The fact that there are so many books on the subject indicates how big the answer to your question really is.
A couple of really great books you might like to try which I've found invaluable are;
Web Application Vulnerabilities Detect, Exploit, Prevent - ISBN-13: 978-1-59749-209-6
Preventing Web Attacks with Apache - ISBN-13: 978-0-321-32128-2
不,time() 不是一个好的盐
在身份验证方面最好不要重新发明轮子,而是回答您的问题,不。 time() 的问题是:
No, time() is not a good salt
It's best not to reinvent the wheel when it comes to authentication, but to answer your question, no. The problem with time():
是的。
看起来,unix 时间戳作为“成员自”字段存储在用户数据库中将是不错的盐。
然而,盐问题是最可以忽略不计的一个。
您还需要注意更多重要的事情:
很可能密码、盐或哈希算法都不是您网站中最薄弱的部分。肯定是一些蹩脚的文件注入或 XSS 或 CSRF。所以,别小题大做。
在典型的 Web 应用程序中谈论 32 个字符长的真正随机字符串就像谈论木制谷仓中的 32 英寸装甲门一样。
说到密码,最重要是密码复杂性。对于弱密码,没有盐或散列算法,即使是超级巧妙、难以置信、困难的算法,也能有所帮助。要求用户使用复杂的密码是一件很痛苦的事情,但如果没有它,其他一切都会变得一团糟。
因此,您首先关心的应该是密码复杂性。要求 12-16 个不同大小写的字符,包括数字和标点符号。
至于盐,
我认为使用时间没有任何好处,因为您必须将其与其他用户数据一起存储。最好使用电子邮件——它足够随机,而且无论如何你已经拥有它了。如果用户更改了电子邮件,请不要忘记重新哈希密码。看来 unix timstamp 将是一个不错的盐,不需要使用电子邮件或其他任何东西。更新
据我所知,很多人仍然无法理解这一点。
就像评论里那个人说的
毫无疑问,他们值得拥有。但用弱密码来完成任务。是。不可能。
如果您的密码很弱,那么没有盐可以保护它。
虽然盐对于在该主题上花费 10 KB 的文本来说并不是那么重要。
Yes.
It seems that a unix timestamp, stored in the user database as a "Member since" field going to be decent salt.
However, salt question is most negligible one.
There are much more important things you have to pay attention to:
Most likely not a password nor salt or hashing algorithm going to be weakest part of your site. Some lame file injection or XSS or CSRF surely is. So, don't make a too big deal of it.
Speaking of a true random string of 32 char long in the typical web-application is like speaking about 32-inch armored door in the wooden barn.
Speaking of passwords, most ever important thing is password complexity. With weak password no salt nor hashing algorithm, even super-ingenious-incredible-hard one, could help. It's a pain to ask users to use complex password, but without it everything else becomes a piece of crap.
So, your first concern should be password complexity. 12-16 characters of different case, including numbers and punctuation is a requirement.
As for the salt,
I see no benefit in using time, as you have to store it along with other user data. Better use a email - it's random enough and you have it already anyway. Don't forget to rehash a password if user changes their email.it seems that unix timstamp going to be a decent salt, no need to use email or anything else.Update
As I can see, many people still unable to get the point.
Like that guy from the comments, saying
They deserve, no doubt. But with weak password the mission. is. impossible.
If your password is weak, then no salt will protect it.
While salt is not that important to spend a 10-kilobyte text on the topic.
Salt 用于通过破坏密码和预先计算的哈希值之间的匹配来防止彩虹攻击。因此,盐的主要任务是使每个用户/密码记录都不同。只要盐对于不同用户来说是不同的,盐的随机化质量并不重要。
Salt is use to prevent rainbow attacks by breaking the match between the password and precomputed hash. So the main task for a salt is to be different for each user/password record. Quality of randomization of the salt doesn't matter much as long as the salt is different for different users.
成员加入论坛/网站的日期通常是可以公开访问的,这与 time() 相同,因此使您的盐毫无用处。
the date when a member joins a forum/website is generally openly access able , which would be same as time() hence making your salt useless.
不!切勿使用当前时间作为盐。您可以使用 java 中的“SecureRandom”之类的东西来生成安全的随机盐。始终使用不可预测的随机数作为盐。
使用时间作为盐只能在一定程度上帮助您消除冲突(因为两个用户可以同时输入相同的密码),但仍然使密码可恢复。
No! Never use the current time as the salt. You can use something like 'SecureRandom' in java to generate a random salt that is secure. Always use an unpredictable random number as the salt.
Using time as the salt will help you to remove collisions only upto a certain extent(because two users can sypply the same passwords at the same time), but still make the passwords recoverable.
用户名应该足够了,也许还有注册时间戳,但您应该将其存储在数据库中的某个位置。无论如何,您用来加盐密码哈希的每个值都应该以某种方式存储,以便您可以重新计算哈希。
使用用户名+时间戳进行加盐是否足够安全?应该是的。为了破解 SHA512 哈希,通常使用彩虹表。用户名+时间戳应该是一个足够唯一的盐,所以网上不可能有一些彩虹表包含预先计算的带有密码的哈希值,这些哈希值是这样加盐的。
The user name should be sufficient enough and perhaps the registration time stamp, but you should store it somewhere in the database. Anyway every value you use to salt your password hash, should be stored some way, so you can recalculate the hash.
Is salting with user name + a time stamp secure enough? It should be. For cracking SHA512 Hashes normally Rainbow Tables are used. A user name + a time stamp should be a salt which is uniquq enough, so there is no way there is some Rainbow Table on the net which contains precalculated hashes with passwords, which are salted this way.