01_Java中的加解密之Base64编码
一.Base64编码:
一. 概念:
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
Base64编码算法原理:
Base64编码要求把3个8位字节(3x8=24)转化为4个6位的字节(4x6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为26=64,这也是Base64名称的由来。编码表见附录!
二. 实现原理:
转码过程例子:原始信息111.利用Base64来进行编码,看最终结果是什么?
3x8=4x6
内存中1个字符占8位.
转换前: 1 1 1
1⃣️.先转成ASCII码表对应的值:
ASCII码表值对应: 49 49 49
2⃣️.转换成对应的2进制:
00110001 00110001 00110001
3⃣️.6个一组进行重新划分为4组:
001100 010011 000100 110001
4⃣️.然后计算机是8位8位的存数 6不够,自动就补两个高位0了.
所以有了高位补0.
科学计算器输入 00001100 00010011 00000100 00110001
得到 12 19 4 49
5⃣️.查对下Base64对照表,得到最终结果: M T E x
先以“迅雷下载”为例: 很多下载类网站都提供“迅雷下载”的链接,其地址通常是加密的迅雷专用下载地址。
其实迅雷的“专用地址”也是用Base64"加密"的,其过程如下:
1.在地址的前后分别添加AA和ZZ;
2.对新的字符串进行Base64编码.
另:Flashget的与迅雷类似,只不过在第一步时加的“料”不同罢了,Flashget在地址前后加的“料”是[FLASHGET],而QQ旋风的干脆不加料,直接就对地址进行Base64编码了.
三. 详细规则:
标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。为解决此问题,可采用一种用于URL的改进Base64编码,它在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3x8 = 4x6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
规则:关于这个编码的规则:
①.把3个字符变成4个字符。
②每76个字符加一个换行符。
③.最后的结束符也要处理。
例子(1)
转换前 11111111, 11111111, 11111111 (二进制)
转换后 00111111, 00111111, 00111111, 00111111 (二进制)
上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。
转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)
四. Java中编码解码过程:
// 加密传入的数据是byte类型的,并非使用decode方法将原始数据转二进制,String类型的数据 使用 str.getBytes()即可
String str = "Hello!";
// 在这里使用的是encode方式,返回的是byte类型加密数据,可使用new String转为String类型
String strBase64 = new String(Base64.encode(str.getBytes(), Base64.DEFAULT));
Log.i("Test", "encode >>>" + strBase64);
// 这里 encodeToString 则直接将返回String类型的加密数据
String enToStr = Base64.encodeToString(str.getBytes(), Base64.DEFAULT);
Log.i("Test", "encodeToString >>> " + enToStr);
// 对base64加密后的数据进行解密
Log.i("Test", "decode >>>" + new String(Base64.decode(strBase64.getBytes(), Base64.DEFAULT)));
CRLF: 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CR LF这一对作为一行的结尾而不是Unix风格的LF.
DEFAULT: 这个参数是默认,使用默认的方法来编码.
NO_PADDING: 这个参数是略去加密字符串最后的”=”.
NO_WRAP: 这个参数意思是略去所有的换行符(设置后CRLF就没用了).
URL_SAFE: 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和_取代+和/.
五. 附录:Base64编码对照表:

六. ASCII码表: