大家好,又见面了,我是你们的朋友全栈君。
回顾 古老的加密技术 中的内容。
加密和编码
在开始之前,让我们确定自己已经了解了 加密(cipher)和 编码 (code)之间的不同。
编码就是一个映射表,它将一些具有意义的单元 (meaningful unit),比如单词、句子、段落,映射到另外一些东西,通常是映射到一小组符号。比如,我们可以使用数字组合 67 去作为单词 Apple 的替代。通常来说,编码是为了节约我们发送消息的时间,因为它使得需要发送的内容变得短小。
编码本用于记录、保存上述提到的映射表,并且在我们编写消息之前,需要先通读下编码本,这样使用编码本中的编码去编写原始的消息内容。只需记住一点,编码需要一个编码本。
那么什么是加密呢?
最重要的一点就是,加密是不涉及语义的。它们只是一些用于处理单个或者一小块字母的机械操作(称为是算法)。比如,在凯撒加密中,我们看到了明文字母 A、B、C 是如何根据一个特定的平移量(比如 3)被映射到 D、E、F 的。在这个情况下,我们不需要使用一个编码本,我们只需要一系列的指令(也就是常说的算法) – “将每一个字母偏移 多少 ”。这个算法需要将一小块信息对加解密双方共享,这些信息被称为是密匙(key),也就是上面例子中的 3。
现在回到开头的问题 – 编码和加密之间有什么不同?编码通常会带入操作对象的语义。而加密的则关心的是操作对象的符号形式。编码被保存在编码本中,而加密则根据算法去变换用于表示的符号。
移位加密
模与移位加密
凯撒加密是移位加密中的一种。移位加密使用模操作去加密和解密消息。移位加密有一个密匙 K,在凯撒加密中,它是一个范围在 0~25 之间的整型。我们只向那些我们希望其看见我们消息的人共享密匙。
如何加密
对于消息中的每一个字母 M:
- 将字母转换成其位于字母表中的顺序,把这个顺序数字记做 X
- 计算:Y = (X + K) mod 26
- 将运算结果 Y 作为字母在字母表中出现的顺序,转成成与其对应的字母
字母表顺序是从 0 开始的: (A=0, B=1, C=2, ...,Y=24, Z=25)
例子:我们和朋友之间使用了密匙 K=19,我们可以像下面这样加密我们的信息 “KHAN”:
K H A N 10 7 0 13 + 19 19 19 19 --------------- 29 26 19 32 (mod 26) 3 0 19 6 --------------- D A T G
所以在应用了值为 19 的密匙之后,我们的消息 “KHAN” 被加密成了 “DATG”。
最后我们将消息 “DATG” 发送给了朋友。
如何解密
对于密文中的每一个字母 C:
- 将字母转换成在字母表中的顺序,从 0 开始。将对应的顺序数字记做 Y。
- 计算:X = (Y – K) mod 26
- 将运算结果 X 作为顺序转成成其对应字母表中的字母。
我们的朋友现在需要按照我们约定的密匙 19 进行解码:
D A T G 3 0 19 6 - 19 19 19 19 -------------------- -16 -19 0 -13 (mod 26) 10 7 0 13 -------------------- K H A N
凯撒加密为什么是不安全的?
加密的目的就是为了阻止一个截取了密文的破解者,去破译那些密文。因为对凯撒加密的移位密匙,我们只有 26 中选择,别人可以轻易的尝试所有可能的 26 个密匙。这种破解方式被称为暴力破解(brute force attack)。
按位异或操作
极限的移位加密
如果你看过之前关于一次一密(one-time pad)的描述的话,你就已经知道它就是极限的移位加密(消息空间的大小、密匙空间的大小以及密文空间的大小三者必须相等)。它引入了一个与明文内容等长的随机移位字码序列。准确地理解为什么一次一密是健壮的、或者说是完美保密的,是非常重要的一件事情。
为了理解为什么,我们首先需要介绍下 AND 与、OR 或、XOR 异或,这几个按位运算。特别是为什么在计算机中处理一次一密需要使用按位异或。按位 Bitwise,简单来说就是我们需要处理各个单独的位,或者说二进制数(binary numbers)。在所有现在的使用计算机的加密方案中,我们都使用二进制数字去表示我们的符号。
加密颜色
让我们通过加密下面 logo 中的一个颜色作为一个形象的开头。
如何将一个颜色转换成一个数?你可以注意到,现在的 HTML 中,使用 三原色色彩模型 RGB color model 作为颜色系统。这个模型的工作是基于将红、绿、蓝三种颜色的光进行叠加以产生其他颜色。
我们可以使用 0~255 之间的数去表示我们需要使用多少的红、绿、或蓝色。黑色的表示就是(0, 0, 0),白色的表示是 (255, 255, 255)。红绿蓝组合在一起一共可以表示 1600(255*255*255) 多万种可能的颜色。
下面让我使用拾色器取出上面 logo 中的绿色:
从上面的拾色器结果的截图中可以看到,红色的值是 156,绿色的值是 181,蓝色的值是 58。如果我们将这些十进制数字转换成对应的二进制: 10011100 + 10110101 + 00111010,为了使它们表现的更加的紧凑,我们将它们拼接到一起得到了下面的一串二进制数:
100111001011010100111010
应用随机的位移
我们假设你通过抛硬币的方式去生成了一串随机的位移序列:
010110100001101111011000
现在让我想一想,应该如何将这串随机序列应用到我们的颜色二进制数上,以达到一次一密的效果。
100111001011010100111010 + 010110100001101111011000 = ?
为了实现一次一密,我们需要选择正确的操作,以使得我们的操作结果可以变成任意的颜色。让我看看三个不同的操作:
如果你正好使用 golang 的话,可以使用这函数:
func EncryptColor(binColor, operator, binKey string) (binCipher string) {
color, _ := strconv.ParseInt(binColor, 2, 32)
key, _ := strconv.ParseInt(binKey, 2, 32)
switch operator {
case "AND":
binCipher = strconv.FormatInt(color&key, 2)
case "OR":
binCipher = strconv.FormatInt(color|key, 2)
case "XOR":
binCipher = strconv.FormatInt(color^key, 2)
}
return binCipher
}
//binCipher := EncryptColor("100111001011010100111010", "AND", "010110100001101111011000")
//fmt.Println(binCipher)
复制代码
AND 按位与
下面是按位与的真值表:
0 AND 0 = 0 0 AND 1 = 0 1 AND 0 = 0 1 AND 1 = 1
让我们试一试:
100111001011010100111010 AND 010110100001101111011000 = 000110000001000100011000
结果将会是一个非常暗的紫色(几乎纯黑)。另外,可以发现,对于 X AND Y 的运算,无论 Y 为何值,结果一定不会大于 X。
OR 按位或
下面是按位或的真值表:
0 OR 0 = 0 0 OR 1 = 1 1 OR 0 = 1 1 OR 1 = 1
让我们试一试:
100111001011010100111010 OR 010110100001101111011000 = 110111101011111111111010
结果将会是一个浅紫色。另外,可以发现,对于 X OR Y 的运算,无论 Y 为何值,结果一定不会小于 X。
XOR 按位异或
下面是按位异或的真值表:
0 XOR 0 = 0 0 XOR** 1** = 1 1 XOR 0 = 1 1 XOR **1 **= 0
让我们试一试:
100111001011010100111010 XOR 010110100001101111011000 = 110001101010111011100010
结果将会是一个比上面更浅的紫色。另外,我们会发现,对于 X XOR Y 的运算,如果 Y 是随机的,那么结果将会是一个因为 Y 而不确定的随机值。对于一个已知的加密颜色,唯一能得到的信息就是,明文内容可能是 1600 万个颜色中的一个。
最后,让我们做一个形象的演示,这样我们就可以实际的感受下一次一密。
为什么一定需要使用按位异或?
非要在 AND、OR、以及 XOR 之中做出一个选择吗?答案是肯定的。并且,知道为什么也是非常重要的。回顾上文,AND 按位与具有 75% 的概率输出 0 以及 25% 的概率输出 1。OR 按位或具有 25% 的概率输出 0,以及 75% 的概率输出 1。而 XOR 按位异或,输出 0 或者 1 的概率各是 50%。
让我们通过加密一个实际的图片去看看三者之间的不同。图片中的人物是 Charles Babbage。
图片中具有上千个细小的色块,它们被称为像素。图片中的每一个像素都可以按照上文介绍的方式,去使用一个 24 位的二进制数去表示。现在,我们把这个图片称为明文图片(或者消息)。
AND
让我们看看如果使用一串随机的二进制数字与明文图片中的像素值进行 AND 操作会发生什么。
可以注意到,明文图片中的大部分像素仍然显示出来了。这是因为,如果明文中的某一位是 0,那么在 AND 之后,对应的结果位上仍然是 0。如果明文的某一位上是 1,恰好对应的随机位上也是 1,那么对应结果位上也是 1。
OR
可以看到,明文中的大量内容同样的显示了出来。这是因为如果明文的某一位上是 1,那么 OR 之后的对应结果位上也会是 1,如果明文的某一位上是 0,并且恰好对应的随机位上也是 0,那么最终对应的结果位上也是 0。
XOR
现在原图中的人物哪去了? 对于明文中的某一位而言,它对应的结果保持不变的可能性只有 50%,也就是说,结果中的某一位是 0 或者 1 的概率各是 50%,这就产生了最终的噪点结果。
对于加密后的图片,没有给别人留下任何的信息。那么在没有密匙的情况下,如果别人想还原图片,只能尝试所有的可能性。
转载于:https://juejin.im/post/5c40057b51882525800520ec
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/107051.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...