我看到哈希和加密算法之间有很多混淆,我想听到一些关于以下方面的专家建议:
什么时候使用哈希和加密 是什么让哈希或加密算法不同(从理论/数学层面) 例如,是什么使得哈希不可逆(没有彩虹树的帮助)
以下是一些类似的SO问题,但没有像我想要的那样详细:
混淆、哈希和加密之间的区别是什么? 加密和哈希的区别
我看到哈希和加密算法之间有很多混淆,我想听到一些关于以下方面的专家建议:
什么时候使用哈希和加密 是什么让哈希或加密算法不同(从理论/数学层面) 例如,是什么使得哈希不可逆(没有彩虹树的帮助)
以下是一些类似的SO问题,但没有像我想要的那样详细:
混淆、哈希和加密之间的区别是什么? 加密和哈希的区别
当前回答
哈希和加密/解密技术的基本概述如下。
散列:
如果你再次哈希任何纯文本,你不能得到相同的纯文本 散列文本中的文本。简单地说,这是一个单向的过程。
加密和解密:
如果你加密任何纯文本与密钥再次你可以 通过使用相同(对称)/不同(不对称)密钥对加密文本进行解密来获得相同的纯文本。
更新: 解决编辑问题中提到的问题。
1. When to use hashes vs encryptions Hashing is useful if you want to send someone a file. But you are afraid that someone else might intercept the file and change it. So a way that the recipient can make sure that it is the right file is if you post the hash value publicly. That way the recipient can compute the hash value of the file received and check that it matches the hash value. Encryption is good if you say have a message to send to someone. You encrypt the message with a key and the recipient decrypts with the same (or maybe even a different) key to get back the original message. credits
2. 是什么使哈希或加密算法不同(从理论/数学层面),即什么使哈希不可逆 (没有彩虹树的帮助)
Basically hashing is an operation that loses information but not encryption. Let's look at the difference in simple mathematical way for our easy understanding, of course both have much more complicated mathematical operations with repetitions involved in it Encryption/Decryption (Reversible): Addition: 4 + 3 = 7 This can be reversed by taking the sum and subtracting one of the addends 7 - 3 = 4 Multiplication: 4 * 5 = 20 This can be reversed by taking the product and dividing by one of the factors 20 / 4 = 5 So, here we could assume one of the addends/factors is a decryption key and result(7,20) is an encrypted text. Hashing (Not Reversible): Modulo division: 22 % 7 = 1 This can not be reversed because there is no operation that you can do to the quotient and the dividend to reconstitute the divisor (or vice versa). Can you find an operation to fill in where the '?' is? 1 ? 7 = 22 1 ? 22 = 7 So hash functions have the same mathematical quality as modulo division and lose the information.
学分
其他回答
对称加密:
对称加密也可以称为共享密钥或共享秘密加密。在对称加密中,一个密钥同时用于加密和解密流量。
非对称加密:
非对称加密也称为公钥加密。非对称加密与对称加密的主要区别在于使用两个密钥:一个用于加密,一个用于解密。最常用的非对称加密算法是RSA。
与对称加密相比,非对称加密施加了很高的计算负担,并且往往要慢得多。因此,它通常不用于保护有效负载数据。相反,它的主要优势在于能够在不安全的媒介(例如Internet)上建立安全通道。这是通过交换公钥来完成的,而公钥只能用于加密数据。互补私钥(从不共享)用于解密。
散列:
最后,哈希是一种不同于加密的加密安全形式。加密是一个两步过程,用于首先加密消息,然后解密消息,而哈希将消息压缩为不可逆的固定长度值或哈希。网络中最常见的两种哈希算法是MD5和SHA-1。
更多信息请点击:http://packetlife.net/blog/2010/nov/23/symmetric-asymmetric-encryption-hashing/
加密和哈希算法的工作原理类似。在每种情况下,都需要在比特之间制造混乱和扩散。简而言之,混淆是在密钥和密文之间创建一个复杂的关系,扩散是在传播每个比特的信息。
许多哈希函数实际上使用加密算法(或加密算法的原语)。例如,SHA-3候选Skein使用threfish作为底层方法来处理每个块。不同之处在于,它们不是保留每个密文块,而是破坏性地、确定性地合并在一起,形成固定的长度
Use hashes when you only need to go one way. For example, for passwords in a system, you use hashing because you will only ever verify that the value a user entered, after hashing, matches the value in your repository. With encryption, you can go two ways. hashing algorithms and encryption algorithms are just mathematical algorithms. So in that respect they are not different -- its all just mathematical formulas. Semantics wise, though, there is the very big distinction between hashing (one-way) and encryption(two-way). Why are hashes irreversible? Because they are designed to be that way, because sometimes you want a one-way operation.
你可以在维基百科上查一下…但既然你想要一个解释,我在这里尽我所能:
哈希函数
They provide a mapping between an arbitrary length input, and a (usually) fixed length (or smaller length) output. It can be anything from a simple crc32, to a full blown cryptographic hash function such as MD5 or SHA1/2/256/512. The point is that there's a one-way mapping going on. It's always a many:1 mapping (meaning there will always be collisions) since every function produces a smaller output than it's capable of inputting (If you feed every possible 1mb file into MD5, you'll get a ton of collisions).
The reason they are hard (or impossible in practicality) to reverse is because of how they work internally. Most cryptographic hash functions iterate over the input set many times to produce the output. So if we look at each fixed length chunk of input (which is algorithm dependent), the hash function will call that the current state. It will then iterate over the state and change it to a new one and use that as feedback into itself (MD5 does this 64 times for each 512bit chunk of data). It then somehow combines the resultant states from all these iterations back together to form the resultant hash.
Now, if you wanted to decode the hash, you'd first need to figure out how to split the given hash into its iterated states (1 possibility for inputs smaller than the size of a chunk of data, many for larger inputs). Then you'd need to reverse the iteration for each state. Now, to explain why this is VERY hard, imagine trying to deduce a and b from the following formula: 10 = a + b. There are 10 positive combinations of a and b that can work. Now loop over that a bunch of times: tmp = a + b; a = b; b = tmp. For 64 iterations, you'd have over 10^64 possibilities to try. And that's just a simple addition where some state is preserved from iteration to iteration. Real hash functions do a lot more than 1 operation (MD5 does about 15 operations on 4 state variables). And since the next iteration depends on the state of the previous and the previous is destroyed in creating the current state, it's all but impossible to determine the input state that led to a given output state (for each iteration no less). Combine that, with the large number of possibilities involved, and decoding even an MD5 will take a near infinite (but not infinite) amount of resources. So many resources that it's actually significantly cheaper to brute-force the hash if you have an idea of the size of the input (for smaller inputs) than it is to even try to decode the hash.
加密功能
They provide a 1:1 mapping between an arbitrary length input and output. And they are always reversible. The important thing to note is that it's reversible using some method. And it's always 1:1 for a given key. Now, there are multiple input:key pairs that might generate the same output (in fact there usually are, depending on the encryption function). Good encrypted data is indistinguishable from random noise. This is different from a good hash output which is always of a consistent format.
用例
Use a hash function when you want to compare a value but can't store the plain representation (for any number of reasons). Passwords should fit this use-case very well since you don't want to store them plain-text for security reasons (and shouldn't). But what if you wanted to check a filesystem for pirated music files? It would be impractical to store 3 mb per music file. So instead, take the hash of the file, and store that (md5 would store 16 bytes instead of 3mb). That way, you just hash each file and compare to the stored database of hashes (This doesn't work as well in practice because of re-encoding, changing file headers, etc, but it's an example use-case).
Use a hash function when you're checking validity of input data. That's what they are designed for. If you have 2 pieces of input, and want to check to see if they are the same, run both through a hash function. The probability of a collision is astronomically low for small input sizes (assuming a good hash function). That's why it's recommended for passwords. For passwords up to 32 characters, md5 has 4 times the output space. SHA1 has 6 times the output space (approximately). SHA512 has about 16 times the output space. You don't really care what the password was, you care if it's the same as the one that was stored. That's why you should use hashes for passwords.
在需要取回输入数据时使用加密。注意“需要”这个词。如果您正在存储信用卡号码,则需要在某个时候将它们取出,但不希望以纯文本形式存储它们。因此,应该存储加密版本,并尽可能保证密钥的安全。
Hash functions are also great for signing data. For example, if you're using HMAC, you sign a piece of data by taking a hash of the data concatenated with a known but not transmitted value (a secret value). So, you send the plain-text and the HMAC hash. Then, the receiver simply hashes the submitted data with the known value and checks to see if it matches the transmitted HMAC. If it's the same, you know it wasn't tampered with by a party without the secret value. This is commonly used in secure cookie systems by HTTP frameworks, as well as in message transmission of data over HTTP where you want some assurance of integrity in the data.
关于密码散列的注意事项:
加密哈希函数的一个关键特征是,它们应该非常快地创建,并且非常难/慢地反转(以至于几乎不可能)。这就给密码带来了一个问题。如果您存储sha512(密码),您没有做任何事情来防止彩虹表或暴力攻击。记住,哈希函数是为了速度而设计的。因此,攻击者只需通过哈希函数运行字典并测试每个结果就可以了。
添加盐有助于解决问题,因为它将一些未知数据添加到散列中。因此,他们不需要找到任何匹配md5(foo)的东西,而是需要找到添加到已知盐中会产生md5(foo.salt)的东西(这要难得多)。但这仍然不能解决速度问题,因为如果他们知道盐,这只是一个运行字典的问题。
有很多处理方法。一种流行的方法被称为键强化(或键拉伸)。基本上,迭代哈希多次(通常是数千次)。这有两个作用。首先,它显著降低了哈希算法的运行速度。其次,如果实现正确(在每次迭代中传递输入和盐),实际上会增加输出的熵(可用空间),减少碰撞的机会。一个简单的实现是:
var hash = password + salt;
for (var i = 0; i < 5000; i++) {
hash = sha512(hash + password + salt);
}
还有其他更标准的实现,如PBKDF2、BCrypt。但是这种技术被相当多的安全相关系统(如PGP、WPA、Apache和OpenSSL)所使用。
最重要的是,哈希(密码)还不够好。哈希(密码+盐)是更好的,但仍然不够好…使用一个扩展散列机制来生成你的密码散列…
关于琐碎拉伸的另一个注意事项
在任何情况下都不要将一个哈希的输出直接返回给哈希函数:
hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
hash = sha512(hash); // <-- Do NOT do this!
}
其原因与碰撞有关。记住,所有哈希函数都存在冲突,因为可能的输出空间(可能输出的数量)小于输入空间。要知道为什么,让我们看看发生了什么。首先,让我们假设sha1()有0.001%的碰撞概率(实际要低得多,但出于演示目的)。
hash1 = sha1(password + salt);
Now, hash1 has a probability of collision of 0.001%. But when we do the next hash2 = sha1(hash1);, all collisions of hash1 automatically become collisions of hash2. So now, we have hash1's rate at 0.001%, and the 2nd sha1() call adds to that. So now, hash2 has a probability of collision of 0.002%. That's twice as many chances! Each iteration will add another 0.001% chance of collision to the result. So, with 1000 iterations, the chance of collision jumped from a trivial 0.001% to 1%. Now, the degradation is linear, and the real probabilities are far smaller, but the effect is the same (an estimation of the chance of a single collision with md5 is about 1/(2128) or 1/(3x1038). While that seems small, thanks to the birthday attack it's not really as small as it seems).
相反,通过每次重新追加盐和密码,将数据重新引入散列函数。所以任何一轮的碰撞都不再是下一轮的碰撞。所以:
hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
hash = sha512(hash + password + salt);
}
具有与本机sha512函数相同的碰撞几率。这就是你想要的。那就用这个吧。
当你不想返回原始输入时,使用哈希,当你想要返回原始输入时,使用加密。
哈希表获取一些输入并将其转换为一些位(通常被认为是一个数字,如32位整数,64位整数等)。相同的输入总是会产生相同的散列,但是在这个过程中你主要会丢失信息,所以你不能可靠地重现原始输入(但是有一些注意事项)。
加密主要保留了您输入到加密函数中的所有信息,只是使任何人在不拥有特定密钥的情况下很难(理想情况下不可能)逆转到原始输入。
哈希的简单例子
这里有一个简单的例子来帮助您理解为什么哈希(在一般情况下)不能返回原始输入。假设我要创建一个1位哈希。我的哈希函数接受一个比特字符串作为输入,如果输入字符串中设置了偶数位,则将哈希值设置为1,如果输入字符串中设置了奇数位,则设置为0。
例子:
Input Hash
0010 0
0011 1
0110 1
1000 0
注意,有许多输入值的哈希值为0,也有许多输入值的哈希值为1。如果你知道哈希值是0,你就不能确定原始输入是什么。
顺便说一下,这个1位哈希并不是完全人为的…看看奇偶校验位。
加密的简单例子
你可以通过使用简单的字母替换来加密文本,比如如果输入是a,你就写B。如果输入是B,你就写c。一直到字母表的末尾,如果输入是Z,你又写a。
Input Encrypted
CAT DBU
ZOO APP
就像简单的哈希示例一样,这种类型的加密在历史上也被使用过。