在信息安全领域,加密、哈希和数据压缩是三个经常被人们提及的概念。然而,很多人对于这三者之间的区别并不十分清楚。本文将试图解释它们之间的不同,并探讨为何不能简单地将数据压缩为固定长度的输出,例如256位或512位。
加密是一种将信息编码的过程,使得只有授权的接收者能够访问信息,而未授权的接收者无法理解信息内容。加密本身并不防止信息被拦截,但它确保拦截者无法理解信息内容。在加密过程中,原始信息或消息(称为明文)通过一个加密算法(密码)进行加密,生成只有解密后才能阅读的密文。
加密的关键在于,可以将加密后的数据反向解密,得到原始数据。如果解密后的数据与原始数据不一致,那么这个过程就不是加密。
假设能够解密SHA或MD5算法,并恢复原始输入,那么会发生什么呢?为了简化例子,假设存在一个名为SHA-2Bit的算法,它总是产生2位的输出,就像SHA256总是产生256位的输出一样。
如果将2位的值输入到SHA-2Bit算法中,得到2位的输出。无论算法内部如何工作,大多数使用SHA256的用户并不需要理解其工作原理。
尝试将所有可能的2位值输入到SHA-2Bit算法中,并观察输出:
输入(二进制) | 输入(十进制) | 输出(二进制) | 输出(十进制) |
---|---|---|---|
00 | 0 | 11 | 3 |
01 | 1 | 00 | 0 |
10 | 2 | 10 | 2 |
11 | 3 | 01 | 1 |
每个输出都是唯一的,这是非常重要的。如果两个不同的输入产生了相同的输出,那么无法解密,因为无法确定开始时是哪个输入。
如果将这些输出作为加密后的值,并尝试反向解密,可以得到原始输入:
输出(二进制) | 输出(十进制) | 输入(二进制) | 输入(十进制) |
---|---|---|---|
11 | 3 | 00 | 0 |
00 | 0 | 01 | 1 |
10 | 2 | 10 | 2 |
01 | 1 | 11 | 3 |
这表明可以使用SHA-2Bit算法加密任何2位的值,并成功解密以恢复原始输入。
如果尝试输入一个3位的值,就会出现问题。因为所有可能的2位输出都已经映射到一个单独的2位输入上。那么,应该如何为3位输入输出一个2位的值呢?可以尝试查看十进制值:
输入(二进制) | 输入(十进制) | 输出(二进制) | 输出(十进制) |
---|---|---|---|
000 | 0 | 11 | 3 |
001 | 1 | 00 | 0 |
010 | 2 | 10 | 2 |
011 | 3 | 01 | 1 |
100 | 4 | ? | ? |
101 | 5 | ? | ? |
110 | 6 | ? | ? |
111 | 7 | ? | ? |
任何尝试选择的2位值都已经被用来映射2位输入值,所以永远无法解密大于或小于2位的值。
与SHA256一样,它有256位,可以产生10^168(或1后面跟着168个零)的不同值,但是提供的512位输入数量是它的两倍。即使是一个包含33个字符的文档也超过了256位!
无论选择什么固定大小作为输出,都不能将比它大一个比特、一个字符或一个字节的数据加密进去,因为绝对会得到重复的输出——而一个重复的值意味着无法保证成功地根据输出恢复原始输入。可能能得到一些东西,但它可能是也可能不是原始文档!
即使使用加密密钥或盐值,也无法解决这个问题。在本例中,甚至没有使用密钥,就像SHA和MD5一样!
重要的是,SHA和MD5不使用密钥,因为它们不是加密算法:它们是哈希算法。哈希算法与加密算法的区别在于,加密可以被逆转,而哈希不能。任何生成固定大小输出的算法都是哈希算法,因为它会产生重复的值,而加密不会,但需要可变长度的输出以确保它。
盐值也无法帮助:它们的作用是改变原始输入,以便两个具有相同密码的用户不会产生相同的“加密密码”表中的值。例如,为了防止所有密码为“Password”的用户仅通过计算表中相同值的数量就能被识别出来!
哈希算法的本质是丢弃信息以产生结果,就像加法一样:如果加2和7,总是得到9——但不能从9中得到2+7,因为0+9、1+8、2+7、3+4、10+(-1)等都给出了相同的值。7+2、2+0+7等也是如此。
这就是为什么流媒体视频服务不仅仅使用SHA来处理整个MP4电影,然后发送给一个256位的值:如果能解密它并恢复整个1GB的电影,相信,他们会这么做的!
哈希也不是压缩,因为压缩(实际上是加密的一种复杂形式)试图产生一个明显小于输入的输出,但它依赖于实际数据和它的“固有模式”来实现压缩。压缩算法无法保证特定的输出大小,输入的微小变化可能导致输出大小的大幅变化。
通常会发现:
是的,MD5已经被官方宣布“破解”,因为有一种方法可以将一些值反向恢复到“可读输入”,但这只在少数情况下有效,并不能保证再生特定的原始输入。这并不意味着它已经成为加密!仍然不应该在新项目中使用它。
2019-06-25:“SHA2”参考遗漏 - 更改为“SHA-2Bit”。感谢@bence98指出!
2019-06-25:“SHA-2Bit”输出到输入的解码澄清。
2019-06-21:虚构的“SHA-2”算法更名为“SHA-2Bit”,以避免与真正的SHA-2算法混淆。感谢@xied75(谢东)并为造成的任何混淆道歉。
2019-06-20:Deeksha整理。