BASE64 是完全可逆的, 他的原理不难理解;
首先需要知道,图片转换成base64并不是加解密,而是编解码,主要的作用不在于安全性,而在于让内容能在各个网关间无错的传输,这才是Base64编码的核心作用。
1 base64编码原理
Base64编码是基于64个字符A-Z,a-z,0-9,+,/的编码方式,因为2的6次方正好为64,所以用6位就可以表示出这64个字符了。一个字节是8位,而6位就能表达64个字符,所以取3个字符(3*8 =24位)就可以凑齐24位,然后把24位转换成4个6位的字符,然后在字节前面都填两个高位 0,形成4个新的字符。
编码流程: 以3个字符为一组,然后针对每组,首先获取每个字符的ASCII编码(字符'a'=97=01100001),然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit 的字节。然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节,然后将这4个8bit的字节转换成十进制
2 base64解码原理
(1)先去掉等号;
(2)再根据编码表,找编码字符对应的编码值;
(3)取各编码值的8位二进制值,去掉每个二进制的前2位的0值,然后连接形成二进制串;
(4)对上述二进制串,从前到后,每8位构成一个字节的数据;多余的末尾0值去掉;
很多的各类的开源框架 都有BASE64 实现, 为什么会这么多呢? 其区别是?
这么多,应该选择哪一个呢?
一般还是 java.util.Base64 吧,如果是 sun.misc.BASE64Encoder , 那么会出现换行。
测试如下:
public static void test() { String path = "C\\\\lk\\\\Documents\\\\mmm\\\\15.驱动\\\\hp M1005 光盘\\\\Espanol\\\\Driver\\\\prn32xl.avi\"rs\\\\lk\\\\Documents\\\\mmm\\\\15.驱动\\\\hp M1005 光盘\\\\Espanol\\\\Driver\\\\prn32xl.avi\""; BASE64Encoder encoder = new BASE64Encoder(); // 每76 个字符一行(why, 源码里面sun.misc.BASE64Encoder.bytesPerLine 返回是57,而转为base64之后,原来每三个字节会变成4个字节,从而 57 / 3 * 4 = 76) System.out.println("base64换行测试:\n" + encoder.encode(path.getBytes())); System.out.println(Base64Utils.encodeToString(path.getBytes())); // 这个就不会换行
System.out.println(Base64.getEncoder().encodeToString(path.getBytes())); // java.util.Base64, 也 不会换行
System.out.println();
/* 下面打印 base64结果为:QkNlRA== base64结果为:QUJD base64结果为:QUJDRA== base64结果为:QUJDRQ== base64结果为:QUJDRWY= */ System.out.println("BASE64 加密规律测试 "); System.out.println("base64结果为:" + encoder.encode("BCeD".getBytes())); System.out.println("base64结果为:" + encoder.encode("ABC".getBytes()));//三个字节会变成4个字节: QUJD; 没有= System.out.println("base64结果为:" + encoder.encode("ABCD".getBytes()));// 同上,前三个字节是相同的,从而base64结果的前4个字节,也是相同的; 为:QUJDRA== System.out.println("base64结果为:" + encoder.encode("ABCE".getBytes()));// 两个= System.out.println("base64结果为:" + encoder.encode("ABCEf".getBytes()));// 一个= System.out.println(); System.out.println("BASE64 URLEncode 乱码问题测试 "); String d = URLEncoder.encode("https://www.jiguang.cn/portal/#/dev/app/1d7dc64658cb11920a965336/info+1"); System.out.println("d = " + d); // :、/、空格、+ 号 全部变为 %xx List<NameValuePair> d1 = URLEncodedUtils.parse(path, StandardCharsets.UTF_8); System.out.println("d1 = " + d1); // 有乱码: d1 = [C\\lk\\Documents\\mmm\\15.q�\\hp M1005 I�\\Espanol\\Driver\\prn32xl.avi"rs\\lk\\Documents\\mmm\\15.q�\\hp M1005 I�\\Espanol\\Driver\\prn32xl.avi"] List<NameValuePair> aaURLEncodedUtils = URLEncodedUtils.parse(path, Charset.forName("GBK"));// 有乱码: 大概因为url urlDecode后无法包含汉字 System.out.println("d1 = " + aaURLEncodedUtils); System.out.println(); /* 下面的 有细微区别: encodeToUrlSafeString = YWJjZWRmZ2hpamtsbW5vcHFyZXN0dXZ3eHl6L0FCQyvmkanmlq_lr4bnoIHliqDlr4bop6Plr4Y= encodeToString = YWJjZWRmZ2hpamtsbW5vcHFyZXN0dXZ3eHl6L0FCQyvmkanmlq/lr4bnoIHliqDlr4bop6Plr4Y= */ System.out.println("BASE64 encodeToUrlSafeString 测试 "); String str = "abcedfghijklmnopqrestuvwxyz/ABC+摩斯密码加密解密"; String s = Base64Utils.encodeToUrlSafeString(str.getBytes()); System.out.println("" + s); s = Base64Utils.encodeToString(str.getBytes()); System.out.println("" + s); System.out.println(); /* 下面的 有细微区别: aHR0cDovL3d3d3cuYmFpZHUuY29tL2RmZGZkZmRmL2RmZGY9d-a1i-ivleWTpnJkZmRmd2UxMjMxajJzK2RmYWRmZGY= aHR0cDovL3d3d3cuYmFpZHUuY29tL2RmZGZkZmRmL2RmZGY9d+a1i+ivleWTpnJkZmRmd2UxMjMxajJzK2RmYWRmZGY= */ String url = "http://wwww.baidu.com/dfdfdfdf/dfdf=w测试哦rdfdfwe1231j2s+dfadfdf"; System.out.println(Base64Utils.encodeToUrlSafeString(url.getBytes())); System.out.println(Base64Utils.encodeToString(url.getBytes())); }
参考:
链接:https://juejin.cn/post/6913814643618086925