Base64Base64是什么?它是一种将字节流转换为可打印字符,并将可打印字符转换为字节流的算法。Base64使用64个可打印字符来表示转换后的数据。准确的说,Base64不是一种加解密算法,而是一种编码解码算法。这就是为什么我使用编码和解码而不是加密和解密的原因。编码原理这里讨论的前提是使用UTF-8编码Base64算法的原理,就是把输入流中的字节分成3个一组,然后每次取6位,转换成对应的in表格中的数据会重复,直到没有剩余的字符。转换表如下:编码过程例如,假设我们要对字符串S.H进行编码:将其转换为十六进制为53、2e、48将十六进制转换为二进制,分别为01010011、00101110、01001000。这里不足8位补0。将其6位各分成一组,分别为010100、110010、111001、001000,转换成十进制、20、50、57、8,然后按照中的转换关系进行转换表中,U,y,5,I即字符串S.H经过Base64算法编码后的结果为Uy5I。编码图如果觉得文字难懂,我把上面的过程以图的形式画出来了,大家可以一起看看。为什么要每三个分组,因为38=24,24=46,所以可以平分。如果我输入少于三个字节怎么办?例如,SH?按照上面的方法:先把它转成十六进制的53、48,再转成二进制的01010011、01001000,再除以6位为一组,就变成010100、110100、1000,再转成十进制就变成了得到20、52、8,最后是U0I。然而,这个结果是不正确的。随便找个工具输入转换一下就知道了,最后的结果就是U0g=。这也意味着当输入的字符少于3个时,不按照前面的方法处理。少于三个字节如何处理?假设待编码的字符串仍然是SH。转换成二进制,01010011、01001000,再分成6位一组,就变成010100、110100、1000。但是可以看出最后一组还不到6位。在这种情况下,将执行在末尾(低位)添加0的操作。完成后会变成010100、110100、100000。但是你会发现这里一共只有18位,不满足3字节一组的原则。在这种情况下,前三组将使用常规Base64编码,缺失的组将使用=填充。这样就会变成20、52、32,再根据表转换得到U0g,再加上最后填的=,最后的结果就是U0g=。下面是示意图。如何处理只有一个字节?同理,如果只有一个字符,则在二进制分组的末尾,不足6位的低位补0,不足4位的分组,直接补=号。例如,假设需要对字符串S进行编码。S的二进制数为01010011,按照6位进行分组,010100,11。第二组明显小于6位,低位补0,低位补0后,结果变成010100、110000,这里只有2组,不到4组,所以这里需要填2=s。将前面两组转化为字符,结果为Uw,结合padding字符,最终结果为Uw==。关于编码,可能有人会说你们都是英文的。英文转十进制再转十六进制,非常方便。比较ASCII码就可以了。中文呢?其实这跟采用的编码类型有关系。同一个中文使用不同的编码,最终的结果可能不同。所以我们这里只讨论使用UTF-8的场景。如果是中文,使用UTF-8编码中文,如果是英文,转换结果和ASCII编码一样。解码原理因为在最终编码的产物中,如果6位的分组少于4组,就会有=作为填充,所以base64之后的一个产物总是可以被4整除的。所以在解密的时候,我们需要处理每次4个字符,将这4个字符编码后转成十进制,再转成二进制。原始序列被重新分组为8位组,即字节组。然后转成十六进制再转回对应的字符。解码过程假设我们需要解密的字符是Uy5I。解密的过程会是这样的:按照一次处理4个字符的原则,根据表将它们转换成十进制20、50、57、8再转换成二进制,小于6位的高位补0,然后分成8位一组。将分组后的位转换为十六进制,得到53、2e、48,最后将十六进制转换为字母,得到S、.、H,也就是说将S.H解码图换成如下图。这里我们处理的是一种理想的情况,因为所有的bits都是刚刚填充的,那么如何用=padding解密base64呢?这里以SH编码后的base64字符串U0g=为例。先根据表格,将其转换成十进制的20、50、32再转换成二进制。分成8位一组,01010011、01001000,然后转成十六进制得到53,48转成字符串得到SH
