总有一些开发的童鞋搞不懂编码与加密的区别。每次都对密码、手机号等信息随便做个 Base64 之后就觉得是加密或者脱敏后的数据了。
实际上,编码之后的数据,依然属于明文!!!
编码与加密的区别
编码就好像家里的大门,砰,关上了。结果就是,可以隔绝小猫、小狗、小苍蝇,但是只要是个正常人,咔,一推,就开了。
加密就好像家里的大门,砰,管上了,咔咔咔,锁上了。结果就是,除非你带钥匙,否则一般人是打不开的(开锁匠、小偷、砸门的,那叫黑客)。
这个比喻,形象不? 他们最大的区别其实就是在于这个钥匙,也就是Key。加密,是有 Key 的,也称之为密钥。而编码,是没有 key 的。
有没有人有疑问?那 MD5 加密就没有 Key 呢…
话说,MD5 加密那只是大家习惯的一种叫法而已,准确的来说,MD5 它叫消息摘要算法,属于哈希算法的一种,它也不是加密算法,而且,很多公司也是明确禁止将 MD5 用作加密用途的。
编码其实就是相当于翻译,就像是把“你好”翻译成了“Hello”,你能说它加密了吗?对于一部分人来说,确实看不懂了,但是对于业内大部分人来说,哪怕是只知道 ABCD 的小朋友,只要脑子里有“英语”这个概念,就算去查字典,也很容易就能查到 “Hello” 其实就等同于 “你好”。
了解了编码与加密的区别,那就直接开始本文的重点——手撕 Base64 编码,十分钟彻底弄懂 Base64 编码原理!
手撕 Base64
以下面这行字符串为例(注意:逗号后面有个空格)
Hello, World!
1. 分组。
将字符串分为 3 个字符一组,最后一组不够三个的用 =
补充
Hel lo, Wo rld !==
2. 转换。
将每组的每个字符转换为对应的 ASCII 编码
H 对应 72
e 对应 101
l 对应 108
以此类推,同上,三个一组
72 101 108
108 111 44
32 87 111
114 108 100
33 = =
3. 转二进制
将 ASCII 编码转为对应的 8 位二进制
01001000 01100101 01101100
01101100 01101111 00101100
00100000 01010111 01101111
01110010 01101100 01100100
00100001 = =
4. 重组
将 8 位二进制码重新组合,原本的每组的 8 3 个二进制数字组成 6 4 形式
010010 000110 010101 101100
011011 000110 111100 101100
001000 000101 011101 101111
011100 100110 110001 100100
001000 01 = =
5. 恢复十进制
将 6 位二进制,依次转为十进制
18 6 21 44 27 6 60 44 8 5 29 47 28 38 49 36 8 16 = =
6. 恢复字符形式
Base64 编码表,共包含 64 个字符(大小写字母 52 个,数字 10 个,特殊字符 2 个),依次(按顺序)分别是:A-Z a-z 0-9 + /
按照上一步中的数字对应转换:
18 对应 S
6 对应 G
21 对应 V
以此类推,得到:
S G V s b G 8 s I F d v c m x k I Q = =
这就是 Hello, World!
的 Base64 编码结果。
代码实现
## 代码中关于占位符没有处理 BASE_CHARS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'] def split_string(string, group_size = 6): return [string[i:i+group_size] for i in range(0, len(string), group_size)] def encode(text): binary_str = ''.join(format(ord(c), '08b') for c in text) # print(binary_str) str = split_string(binary_str, 6) result = '' right_padding = '' i = 0 for a in str: i = i+1 # print(i % 4) if(i % 4 == 2): right_padding = "==" if(i % 4 == 1): right_padding = "=" c = int(format(a, '06'), 2) cc = BASE_CHARS[c] result += cc result += right_padding return result def decode(text): result = '' text = text.replace('=', '') binary_str = ''.join("{:06d}".format(int(bin(BASE_CHARS.index(t))[2:])) for t in text) print(binary_str) str = split_string(binary_str, 8) for a in str: c = chr(int(format(a, '08'), 2)) result += c ... return result ################################### text = "Hello, World!" result = encode(text) print(result) result = decode(result) print(result)