密码和不同类型的加密 [英] Passwords and different types of encryption

查看:163
本文介绍了密码和不同类型的加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,我知道,类似的问题已经被问到了数百万和数十亿次,但是由于他们大多数都有不同的口味,我得到了我自己的一个。



目前,我正在一个旨在在全国各地推出的网站,因此需要为用户系统提供某种保护。



我最近读了很多关于密码加密,散列,盐渍的文章..你命名了,但阅读了很多文章后,我感到困惑。



一个说明白SHA512加密对于密码来说就足够了,其他人说你不得不使用salt,不管你做什么,然后有人说你应该建立一个全新的密码加密机器,因为没有一个人将会得到它。



现在我使用 hash_hmac(); SHA512,加号,密码获取随机SHA1盐和最后一部分,定义随机md5();键。对于我们大多数人来说,这听起来很安全,但是是吗?

我最近在这里阅读过,所以 bcrypt(); (现在称为 crypt(); 与Blowfish散列)是最安全的方式。阅读PHP手册后,关于 crypt(); 和相关的东西,我很困惑。



基本上,问题是的,我的 hash_hmac(); 打破了 Blowfished crypt(); 或者反之亦然?



另外还有一个更安全的密码哈希选项?

解决方案

正确应用加密技术的关键是定义足够的精度你以后的属性。



通常,当有人想要哈希密码,它在以下环境中:服务器正在验证用户;用户通过机密渠道(HTTPS ...)显示他们的密码。因此,服务器必须存储用户密码,或者至少存储可用于验证密码的东西。我们不想按原样存储密码,因为获取对服务器数据库的读访问权的攻击者将会学习所有密码。这是我们的攻击模式



密码是适合普通用户的大脑的东西,因此它不能完全无可估量。一些用户将选择具有高熵的非常长的密码,但大多数用户将选择不高于32位的熵密码。这是一种说法,攻击者必须在找到正确的密码之前平均少于2个(约2亿)个密码才能尝试。



无论服务器存储什么,验证密码都足够了;因此,我们的攻击者拥有尝试密码所需的所有数据,只能受到他所能掌握的计算能力的限制。这被称为离线字典攻击。



我们必须假设我们的攻击者可以破解一个密码。在这一点上,我们可能希望有两个属性:


  1. 破解一个密码应该是困难的(几天或几周,而不是秒);

  2. crack 两个密码应该是两次,就像打破一样。

这两个属性要求不同的对策,可以组合。



1。缓冲哈希



哈希功能很快。计算能力便宜。作为数据点,使用SHA-1作为散列函数,以及130 $ NVIDIA图形卡,我可以每秒散布160万个密码。大约13秒钟内支付2 31 费用。因此,SHA-1对于安全性来说太快了。



另一方面,用户在1μs中进行身份验证,并且在1ms之间进行身份验证不会有任何差异。所以这里的诀窍就是使哈希函数以一种缓慢的方式进行扭曲。



例如,给定哈希函数 H ,使用定义为:



H'(x)= H(x || x || x || ... || x)



其中' || '表示连接。简单来说,重复输入足够的时间,以便计算 H'函数需要一些不可忽视的时间。所以你设定一个时间目标,例如1ms,并调整达到该目标所需的重复次数。 10ms意味着您的服务器将能够以每秒10个用户的身份验证每秒10个用户。请注意,我们正在谈论一个存储散列密码的服务器,用于其自己的不必要的使用,因此这里没有互操作性问题:每个服务器可以使用特定的重复计数,为其权力量身定制。



现在假设攻击者可以拥有100倍的计算能力;例如攻击者是一个无聊的学生 - 许多安全系统的恐惧 - 可以在他的大学校园内使用数十台计算机。此外,攻击者可能会使用更为彻底优化的哈希函数实现方法(您正在谈论PHP,但是攻击者可以进行汇编)。此外,攻击者是患者:用户不能等待超过一秒钟的时间,但是无聊的学生可能会尝试几天。然而,尝试二十亿个密码仍然需要大约3天的计算时间。这不是最终安全的,但是在一台便宜的PC上比13秒好多了。



2。盐



一个是一个公共数据,它与密码哈希,以防止共享。



共享是当攻击者可以通过多次攻击的密码重新使用哈希算法时发生的情况。当攻击者有几个散列密码(他读整个散列密码数据库)时,会发生什么:每当他隐藏一个潜在密码时,他可以查看所有散布了他试图攻击的密码。我们称之为并行字典攻击。另一个共享实例是当攻击者可以构建一个预先计算的散列密码表,然后重复使用他的表(通过简单查找)。传说中的彩虹表仅仅是一个预先计算的表格的特殊情况(这只是一个时间内存的权衡,允许使用比硬盘上更适合的预计算表;但是构建该表仍然需要散列每个潜在的密码)。空时智慧,平行攻击和预计算表是相同的攻击。<​​/ p>

盐化失败共享。 salt是一个更改哈希过程的公共数据元素(可以说salt 选择整个不同功能的哈希函数)。盐的一点是每个密码都是唯一的。攻击者不能再共享破解的努力,因为任何预先计算的表将必须使用特定的盐,并且对使用不同盐的密码进行加密是无用的。



盐必须用于验证密码,因此服务器必须为每个散列密码存储用于散列该密码的盐值。在数据库中,这只是一个额外的列。或者您可以在单个blob中连接盐和哈希密码;这只是一个数据编码的问题,它取决于你。



假设 S 是盐(即一些字节),散列密码的过程 p 是: H'(S || p)(与上一节定义的 H'函数)。就是这样!



盐的含义是尽可能地对每个散列密码都是唯一的。实现这一点的一个简单方法是使用随机盐:每当创建或更改密码时,使用随机生成器来获取16个随机字节。 16个字节应该足以使盐重复使用非常不可能。请注意,对于每个密码,盐应该是唯一的:使用用户名作为盐不够(一些不同的服务器实例可能具有相同名称的用户 - 存在多少bob - 还有一些用户更改密码,新密码不应该与以前的密码一样使用)。



第3。散列函数的选择



哈希函数是通过哈希函数H 构建的。一些传统的实现使用加密算法扭曲成哈希函数(例如,用于Unix的 crypt()的DES)。虽然不正确(密码没有加密,因为没有解密过程,正确的术语是哈希密码),但这已经促进了使用加密密码表达式。但是,使用专门用于散列的真正哈希函数似乎更为安全。



最常用的哈希函数有:MD5,SHA-1,SHA- 256,SHA-512(后两者统称为SHA-2)。 MD5和SHA-1中存在一些缺点。这些弱点对于一些使用而言有严重的影响,但不是,因为上述内容(缺点是关于碰撞,而我们在这里的前图像阻力)。然而,更好的公共关系选择SHA-256或SHA-512:如果您使用MD5或SHA-1,您可能需要证明自己。 SHA-256和SHA-512的输出尺寸和性能不同(在某些系统上,SHA-256比SHA-512快得多,其他SHA-512比SHA-256快)。然而,性能不是这里的一个问题(不管哈希函数本身的速度如何,我们通过输入重复使速度慢得多),并且256位的SHA-256输出是足够的。将哈希函数输出截断为第一个 n 位,以便节省存储成本,只要您保持至少128位( n> = 128 )。



4。结论



无论何时创建或修改密码,生成一个新的随机盐>(16字节)。然后将密码 p 哈希为SHA-256(S || p || S || p || S || p || ... || S || p) em>其中' S || p '模式重复足够多的时间,哈希过程需要10ms。存储 S 和哈希结果。要验证用户密码,请检索 S ,重新计算哈希值,并将其与存储的值进行比较。



您将会更快,更快乐。


I know, I know, similar questions have been asked millions and billions of times already, but since most of them got a different flavor, I got one of my own.

Currently I'm working on a website that is meant to be launched all across my country, therefore, needs some kind of protection for user system.

I've been lately reading alot about password encryption, hashing, salting.. you name it, but after reading that much of articles, I get confused.

One says that plain SHA512 encryption is enough for a password, others say that you have to use "salt" no matter what you would do, and then there are guys who say that you should build a whole new machine for password encryption because that way no one will be able to get it.

For now I'm using hash_hmac(); with SHA512, plus, password gets random SHA1 salt and the last part, defined random md5(); key. For most of us it'll sound secure, but is it?
I recently read here on SO, that bcrypt(); (now known as crypt(); with Blowfish hashing) is the most secure way. After reading PHP manual about crypt(); and associated stuff, I'm confused.

Basicly, the question is, will my hash_hmac(); beat the hell out of Blowfished crypt(); or vice-versa?

And one more, maybe there are more secure options for password hashing?

解决方案

The key to proper application of cryptography is to define with enough precision what properties you are after.

Usually, when someone wants to hash passwords, it is in the following context: a server is authenticating users; users show their password, through a confidential channel (HTTPS...). Thus, the server must store user passwords, or at least store something which can be used to verify a password. We do not want to store the passwords "as is" because an attacker gaining read access to the server database would then learn all passwords. This is our attack model.

A password is something which fits in the brain of the average user, hence it cannot be fully unguessable. A few users will choose very long passwords with high entropy, but most will select passwords with an entropy no higher than, say, 32 bits. This is a way of saying that an attacker will have to "try" on average less than 231 (about 2 billions) potential passwords before finding the right one.

Whatever the server stores, it is sufficient to verify a password; hence, our attacker has all the data needed to try passwords, limited only by the computing power he can muster. This is known as an offline dictionary attack.

One must assume that our attacker can crack one password. At that point we may hope for two properties:

  1. cracking a single password should be difficult (a matter of days or weeks, rather than seconds);
  2. cracking two passwords should be twice as hard as cracking one.

Those two properties call for distinct countermeasures, which can be combined.

1. Slow hash

Hash functions are fast. Computing power is cheap. As a data point, with SHA-1 as hash function, and a 130$ NVidia graphic card, I can hash 160 millions passwords per second. The 231 cost is paid in about 13 seconds. SHA-1 is thus too fast for security.

On the other hand, the user will not see any difference between being authenticated in 1µs, and being authenticated in 1ms. So the trick here is to warp the hash function in a way which makes it slow.

For instance, given a hash function H, use another hash function H' defined as:

H'(x) = H(x || x || x || ... || x)

where '||' means concatenation. In plain words, repeat the input enough times so that computing the H' function takes some non-negligible time. So you set a timing target, e.g. 1ms, and adjust the number of repetitions needed to reach that target. 10ms means that your server will be able to authenticate 10 users per second at the cost of only 10% of its computing power. Note that we are talking about a server storing a hashed password for its own ulterior usage, hence there is no interoperability issue here: each server can use a specific repetition count, tailored for its power.

Suppose now that the attacker can have 100 times your computing power; e.g. the attacker is a bored student -- the nemesis of many security systems -- and can use dozens of computers across his university campus. Also, the attacker may use a more thoroughly optimized implementation of the hash function H (you are talking about PHP but the attacker can do assembly). Moreover, the attacker is patient: users cannot wait for more than a fraction of a second, but a sufficiently bored student may try for several days. Yet, trying 2 billions passwords will still require about 3 full days worth of computing. This is not ultimately secure, but is much better than 13 seconds on a single cheap PC.

2. Salts

A salt is a piece of public data which you hash with the password in order to prevent sharing.

"Sharing" is what happens when the attacker can reuse his hashing efforts over several attacked passwords. This is what happens when the attacker has several hashed passwords (he read the whole database of hashed passwords): whenever he hashes one potential password, he can look it up against all hashed passwords he is trying to attack. We call that a parallel dictionary attack. Another instance of sharing is when the attacker can build a precomputed table of hashed passwords, and then use his table repeatedly (by simple lookups). The fabled rainbow table is just a special case of a precomputed table (that's just a time-memory trade-off which allows for using a precomputed table much bigger than what would fit on a hard disk; but building the table still requires hashing each potential password). Space-time wise, parallel attacks and precomputed tables are the same attack.

Salting defeats sharing. The salt is a public data element which alters the hashing process (one could say that the salt selects the hash function among a whole set of distinct functions). The point of the salt is that it is unique for each password. The attacker can no longer share cracking efforts because any precomputed table would have to use a specific salt and would be useless against a password hashed with a distinct salt.

The salt must be used to verify a password, hence the server must store, for each hashed password, the salt value which was used to hash that password. In a database, that's just an extra column. Or you could concatenate the salt and the hash password in a single blob; that's just a matter of data encoding and it is up to you.

Assuming S to be the salt (i.e. some bytes), the hashing process for password p is: H'(S||p) (with the H' function defined in the previous section). That's it!

The point of the salt is to be, as much as possible, unique to each hashed password. A simple way to achieve that is to use random salts: whenever a password is created or changed, use a random generator to get 16 random bytes. 16 bytes ought to be enough to make salt reuse highly improbable. Note that the salt should be unique for each password: using the user name as a salt is not sufficient (some distinct server instances may have users with the same name -- how many "bob"s exist out there ? -- and, also, some users change their password, and the new password should not use the same salt than the previous password).

3. Choice of hash function

The H' hash function is built over a hash function H. Some traditional implementations have used encryption algorithms twisted into hash functions (e.g. DES for Unix's crypt()). This has promoted the use of the "encrypted password" expression, although it is not proper (the password is not encrypted because there is no decryption process; the correct term is "hashed password"). It seems safer, however, to use a real hash function, designed for the purpose of hashing.

The most used hash functions are: MD5, SHA-1, SHA-256, SHA-512 (the latter two are collectively known as "SHA-2"). Some weaknesses have been found in MD5 and SHA-1. Those weaknesses have serious impact for some usages, but not for what is described above (the weaknesses are about collisions, whereas we work here on preimage resistance). However, it is better public relations to choose SHA-256 or SHA-512: if you use MD5 or SHA-1, you may have to justify yourself. SHA-256 and SHA-512 differ by their output size and performance (on some systems, SHA-256 is much faster than SHA-512, and on others SHA-512 is faster than SHA-256). However, performance is not an issue here (regardless of the hash function intrinsic speed, we make it much slower through input repetitions), and the 256 bits of SHA-256 output are more than enough. Truncating the hash function output to the first n bits, in order to save on storage costs, is cryptographically valid, as long as you keep at least 128 bits (n >= 128).

4. Conclusion

Whenever you create or modify a password, generate a new random salt S (16 bytes). Then hash the password p as SHA-256(S||p||S||p||S||p||...||S||p) where the 'S||p' pattern is repeated enough times to that the hashing process takes 10ms. Store both S and the hash result. To verify a user password, retrieve S, recompute the hash, and compare it with the stored value.

And you will live longer and happier.

这篇关于密码和不同类型的加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆