散列算法和加密算法之间的基本区别

9 浏览
0 Comments

散列算法和加密算法之间的基本区别

我看到很多关于哈希和加密算法之间的混淆,我想听听一些更专业的建议,关于以下问题:

  1. 何时使用哈希和加密
  2. 哈希或加密算法的不同之处(从理论/数学层面上)

    即什么使哈希不可逆(无需彩虹树的帮助)

以下是一些类似的SO问题,但没有提供我所寻找的详细信息:

混淆、哈希和加密之间的区别是什么?

加密和哈希之间的区别

0
0 Comments

哈希函数和加密算法之间的根本区别

哈希函数和加密算法之间的根本区别在于它们的目的和使用方式。哈希函数用于将输入数据转化为固定长度的输出,通常用于数据的完整性校验和唯一标识。而加密算法则是为了保护数据的机密性,将输入数据转化为密文,只有拥有密钥的人才能解密得到原始的明文数据。

哈希函数的主要作用是生成唯一的标识符,用于验证数据的完整性和唯一性。它的输入可以是任意长度的数据,但输出的哈希值是固定长度的。一个好的哈希函数应该具有无冲突性和抗碰撞性,即不同的输入数据应该生成不同的哈希值,而相同的输入数据应该生成相同的哈希值。常见的哈希函数有MD5、SHA-1和SHA-256等。

与哈希函数不同,加密算法是一种将明文转化为密文的过程,以保护数据的机密性。加密算法通常使用密钥对数据进行加密,只有拥有正确密钥的人才能解密得到原始的明文数据。加密算法可以分为对称加密算法和非对称加密算法。对称加密算法使用同一个密钥进行加密和解密,效率高但密钥管理困难;非对称加密算法使用一对密钥,公钥用于加密,私钥用于解密,安全性较高但运算速度较慢。常见的加密算法有DES、AES和RSA等。

哈希函数和加密算法之间的区别可以通过以下几个方面进行总结:

1. 目的不同:哈希函数的目的是生成唯一的标识符,用于数据的完整性校验和唯一标识;而加密算法的目的是保护数据的机密性,将明文转化为密文。

2. 输出长度不同:哈希函数的输出是固定长度的哈希值,不论输入的数据长度如何,输出的哈希值长度是固定的;而加密算法的输出长度与输入数据长度相同。

3. 可逆性不同:哈希函数是单向函数,即无法通过哈希值反推出原始的输入数据;而加密算法是可逆的,可以通过密文和正确的密钥还原出原始的明文数据。

4. 安全性要求不同:哈希函数要求具有无冲突性和抗碰撞性,即不同的输入数据应该生成不同的哈希值,而相同的输入数据应该生成相同的哈希值;而加密算法要求具有较高的安全性,能够抵抗各种攻击手段。

哈希函数和加密算法是两种不同的算法,用于不同的目的。哈希函数主要用于数据的完整性校验和唯一标识,而加密算法主要用于数据的机密性保护。在实际应用中,根据具体的需求和安全要求,选择合适的算法进行数据处理和保护。

0
0 Comments

哈希和加密算法之间的基本区别

在计算机科学中,哈希和加密算法是两种常见的算法。哈希函数提供了一个将任意长度的输入映射到一个(通常)固定长度或较小长度的输出的方法。它可以是简单的crc32,也可以是像MD5或SHA1/2/256/512这样的全面的加密哈希函数。哈希函数是一个单向映射,意味着它是一个多对一的映射,因为每个函数产生的输出都比其输入小(如果将每个可能的1mb文件输入到MD5中,你会得到大量的碰撞)。

哈希函数之所以难以(或在实践中不可能)逆向是因为它们的内部工作方式。大多数加密哈希函数会对输入集进行多次迭代以产生输出。因此,如果我们查看输入的每个固定长度块(这取决于算法),哈希函数将把其称为当前状态。然后,它将迭代状态并将其更改为新状态,并将其作为反馈输入到自身中(MD5对每个512位数据块进行64次迭代)。然后,它以某种方式将所有这些迭代的结果状态组合在一起形成结果哈希。

现在,如果你想解码哈希,首先你需要找出如何将给定的哈希拆分为其迭代状态(对于小于数据块大小的输入,有1种可能性,对于较大的输入,有多种可能性)。然后你需要逆转每个状态的迭代。现在,为了解释为什么这非常困难,想象一下从以下公式中推断a和b:10 = a + b。有10种正数组合可以满足这个等式。现在重复这个过程多次:tmp = a + b; a = b; b = tmp。对于64次迭代,你将有超过10^64种可能性要尝试。而这只是一个简单的加法,其中一些状态在迭代到迭代之间保持不变。真正的哈希函数执行的操作比这个多得多(MD5在4个状态变量上执行约15个操作)。由于下一次迭代取决于上一次的状态,并且上一个状态在创建当前状态时被销毁,几乎不可能确定导致给定输出状态的输入状态(对于每次迭代都是如此)。结合大量的可能性,即使解码一个MD5也需要几乎无限(但不是无限)的资源。需要的资源如此之多,以至于如果你知道输入的大小(对于较小的输入)的话,暴力破解哈希甚至比尝试解码哈希要便宜得多。

加密函数提供了一个任意长度输入和输出之间的一对一映射。它们是可逆的,关键是通过某种方法进行逆向映射,并且对于给定的密钥始终是一对一的。尽管可能有多个输入:密钥对可以生成相同的输出(实际上通常如此,取决于加密函数),但好的加密数据在外观上与随机噪声无异。这与良好的哈希输出不同,后者始终具有一致的格式。

哈希函数的用途是在需要进行值的比较但无法存储明文表示(由于各种原因)时使用。密码非常适合这种用例,因为出于安全原因(也应该如此),你不希望以明文形式存储密码。但是,如果你想检查文件系统中是否存在盗版音乐文件怎么办?存储每个音乐文件的3mb将是不切实际的。因此,取文件的哈希值,然后存储它(MD5将存储16个字节而不是3mb)。这样,你只需要计算每个文件的哈希值并与存储的哈希值数据库进行比较(由于重新编码、更改文件头等原因,这在实践中效果不是很好,但这是一个示例用例)。

在检查输入数据的有效性时使用哈希函数。这是它们设计的目的。如果你有两个输入,并想要检查它们是否相同,请将它们都通过哈希函数运行。对于较小的输入大小(假设哈希函数良好),碰撞的概率极低。这就是为什么推荐在密码中使用哈希函数的原因。对于长度最多为32个字符的密码,md5的输出空间是4倍。SHA1的输出空间是6倍(大约)。SHA512的输出空间大约是16倍。你真正关心的不是密码究竟是什么,而是它是否与存储的密码相同。这就是为什么应该在密码中使用哈希函数的原因。

当你需要将输入数据取回时,使用加密。请注意“需要”这个词。如果你正在存储信用卡号码,你需要在某个时候将其取回,但不希望以明文形式存储。因此,存储加密版本并尽可能安全地保留密钥。

哈希函数也非常适合对数据进行签名。例如,如果你使用HMAC,你可以通过对数据和已知但未传输的值(密钥)进行哈希来对数据进行签名。因此,你发送明文和HMAC哈希。然后,接收者只需使用已知的值对提交的数据进行哈希,并检查是否与传输的HMAC匹配。如果相同,你就知道它没有被没有密钥的一方篡改。这在HTTP框架的安全cookie系统中经常使用,以及在通过HTTP传输数据的消息传输中,你希望对数据的完整性有一定的保证。

关于密码哈希的一个注释:

加密哈希函数的一个关键特点是它们应该创建非常快,并且非常难/慢以逆向(以至于实际上几乎不可能)。这对于密码是一个问题。如果你存储`sha512(password)`,你对彩虹表或暴力破解攻击没有任何防御措施。请记住,哈希函数的设计是为了速度。因此,攻击者只需将字典通过哈希函数运行并测试每个结果,这是微不足道的。

添加盐有助于解决这个问题,因为它在哈希中添加了一些未知数据。因此,他们不仅需要找到与已知盐结合产生`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(password)`是不够的。`hash(password + salt)`更好,但仍然不够好...使用拉伸哈希机制来生成密码哈希...

关于简单拉伸的另一个注释:

绝对不要将一个哈希的输出直接输入到哈希函数中:

hash = sha512(password + salt); 
for (i = 0; i < 1000; i++) {
    hash = sha512(hash); // <-- 不要这样做!
}

这样做的原因与碰撞有关。请记住,所有哈希函数都存在碰撞,因为可能的输出空间(可能的输出数量)比输入空间小。让我们看看发生了什么。为了说明这一点,假设`sha1()`的碰撞机率为0.001%(实际上远远小于此值,但为了演示目的)。

hash1 = sha1(password + salt);

现在,`hash1`的碰撞概率为0.001%。但是当我们执行下一个`hash2 = sha1(hash1);`时,所有`hash1`的碰撞自动变成`hash2`的碰撞。所以现在,`hash2`的碰撞概率为0.002%。这是两倍的机会!每次迭代都会将`0.001%`的碰撞概率添加到结果中。因此,1000次迭代后,碰撞的机会从微不足道的0.001%变为1%。现在,退化是线性的,实际概率要小得多,但效果是相同的(使用`md5`的单个碰撞机会的估计约为1/(2^128)或1/(3x10^38)。尽管看起来很小,但由于生日攻击的原因,它实际上并不像看起来的那么小)。

相反,通过在每次迭代中重新附加盐和密码,你重新引入了数据到哈希函数中。因此,任何特定轮次的碰撞不再是下一个轮次的碰撞。所以:

hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
    hash = sha512(hash + password + salt);
}

和原生的`sha512`函数具有相同的碰撞概率。这就是你想要的。使用这个方法。

总之,哈希和加密算法之间的基本区别在于哈希是单向函数,而加密是双向函数。哈希是一种将明文文本混淆以生成唯一消息摘要的函数,而加密则提供了一种将明文和密文相互转换的方法。哈希函数适用于在需要比较值但无法存储明文表示时使用,例如密码和数据验证。加密函数适用于需要在后续操作中检索明文数据的情况,例如信用卡号码。

0
0 Comments

哈希和加密算法之间的基本区别是什么?

哈希算法是一种单向过程,通过对明文进行哈希,得到的哈希文本无法还原为原始的明文。而加密算法是通过使用密钥对明文进行加密,再通过使用相同(对称加密)或不同(非对称加密)的密钥对加密文本进行解密,从而得到原始的明文。

哈希算法的应用场景是在需要向他人发送文件时。如果担心文件可能被他人拦截并篡改,可以公开发布文件的哈希值。这样,接收者可以计算接收到的文件的哈希值,并检查它是否与公开的哈希值匹配,以确保接收到的文件是正确的。

而加密算法适用于需要向他人发送消息的场景。可以使用密钥对消息进行加密,接收者使用相同(或不同)的密钥对加密文本进行解密,从而得到原始的消息。

从理论/数学的角度来看,哈希算法和加密算法的主要区别在于哈希算法是一种会丢失信息的操作,而加密算法不会。简单地说,加密算法是可逆的,而哈希算法则不可逆。

例如,在加密/解密过程中,加法和乘法都是可逆的。加法的结果可以通过减去其中一个加数来还原,乘法的结果可以通过除以其中一个因子来还原。因此,可以将其中一个加数/因子视为解密密钥,而结果(加法的和/乘法的积)视为加密后的文本。

而在哈希算法中,模除是一个不可逆的过程。无法通过对商和被除数进行操作来重建除数(或反之)。因此,哈希函数具有与模除相同的数学特性,会丢失信息。

总之,哈希算法和加密算法在实现上有明显的区别,哈希算法是一种单向过程,而加密算法是一种可逆过程。这些算法的应用场景和数学特性也有所不同。

0