Skip to content

Latest commit

 

History

History
60 lines (54 loc) · 2.89 KB

从RFC4648中理解Base64算法.md

File metadata and controls

60 lines (54 loc) · 2.89 KB

一、前置知识点

Base64算法是一种编码算法,它是采用常见的64个字符来表示做数据映射的表,分别是A-Z、a-z、+、/。

64对应的二进制是0b111111,也就是

2^6 = 64

换句话说,6个bit就能表示一个字符,而正常的字节对应的8bit,要把正常字符和编码后的字符串联起来的话那么就需要找出它们的最小公倍数,以最小公倍数所代表的长度来划分,那么8和6的公倍数是24,也就可以这么理解,3个正常字符实际上对应的是4个编码字符,举例说明下

lin的正常二进制编码
01101100|01101001|01101110

变成base64的编码
011011|000110|100101|101110

# 正常来说8bit组成一个字节,所以划分成base64的编码之后还需要在前面补两个0变成正常的8bit

变成十进制
27|6|37|46

获取映射表
bGlu

这样就得到了最终的编码,所以就可以理解正常字符中每三个字符会对应编码后的四个字符,如果按长度3来切分存在余数的话(例如1、2),就使用0来做填充,而填充的输出通常用=来表示,所以一般都能看到在base64编码后的字符存在=的情况,这样就表示字符长度非3的倍数(一般余数为1的话就是两个=)

二、算法流程

1 分组并获取映射

获取输入字符的长度,每3个字符为一组来进行处理

第一个字符的处理:获取字符的二进制前6位,并获取对应的映射

ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);

第二个字符的处理:第一个字符还剩余两位,取出低位2个bit,同时左移四位并取出第二个字符的前4个bit

ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);

第三个字符的处理:第二个字符的后4个bit还没取出,取出并取第三个字符的前2个bit

ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);

第四个字符的处理:直接取出剩余的低六位即可

ret.push_back(base64_chars_[  bytes_to_encode[pos + 2] & 0x3f]);

3 尾端处理

剩余两个字符的情况

ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
ret.push_back(trailing_char);

剩余一个字符的情况

ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
ret.push_back(trailing_char);
ret.push_back(trailing_char);

三、解码算法流程

解码流程就可以当做编码流程的逆向过程,将每个编码根据映射表转化成索引->二进制,再组合起来即可

总结

综合上面所讲到的MD5算法原理,可以看出Base64还是比较简单易懂的,与最终结果相关的正如上面所讲到的有一个关键点,理解它们的含义以及作用在后续我们对Base64算法进行魔改的时候是很有帮助的