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