Base64加密轉換原理與代碼實現


一、Base64實現轉換原理

  它是用64個可打印字符表示二進制所有數據方法。由於2的6次方等於64,所以可以用每6個位元(bit)為一個單元,對應某個可打印字符。我們知道三個字節(byte)有24個位元,就可以剛好對應於4個Base64單元,即3個字節需要用4個Base64的可打印字符來表示。

  · 可打印符號:

  在Base64中的可打印字符包括字母A-Z、a-z、數字0-9 ,這樣共有62個字符,此外兩個可打印符號在不同的系統中一般有所不同。但是,我們經常所說的Base64另外2個字符是:“+/”。這64個字符,所對應表如下:

編號 字符   編號 字符   編號 字符   編號 字符
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

  

  仔細思考一下,你會很快發現,一個問題,就是每次轉換的字節數不一定就是24的整數倍,會出現有多余不足六位的情況,在base64中處理的方法是加零湊夠六位,但是這樣一來在解碼的時候就會出現多余的位  這該怎么辦呢? base64想到了一個很好的解決辦法。這個辦法就是在 base64湊零的同時,還要滿足湊出來的位數是8的倍數,不然就加一個或者兩個特殊的六位  =  符號。為什么是一個或者兩個=符號呢? 因為多個8位轉為6位 只會出現 剩余 2位,4位的情況,剩余2位 只需要一個 表示六位的 =  便可變為8的整數;而剩余4位 需要兩個表示6位的 = 便可以變成16 是8的整數。然后在解密的時候不解析 =即可。

     之所以位的總數需要湊成8的倍數,是因為base64主要用於加密后的數據傳送,而在傳送機制中都認為傳送的最小單位是按照字節算的,所以不能出現不是位總數不是8的倍數的情況,在接收到數據后,按順序將6位的base64直接按照順序解密成字節就完成解密了。

· 轉換過程:

    ① 將三個byte(字節)的數據,先后放入一個24bit(位)的緩沖區中,先來的byte占高位。數據不足 3 byte的話,於緩沖區中剩下的bit用0補足。

    ② 然后,每次取出6個bit,按照其值選擇 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 中的字符作為編碼后的輸出。不斷進行,直到全部輸入數據轉換完成。

       ③    如果最后剩下兩個輸入數據,在編碼結果后加1個“=”;

      如果最后剩下一個輸入數據,編碼結果后加2個“=”;

      如果沒有剩下任何數據,就什么都不要加,這樣才可以保證資料還原的正確性。

   編碼后的數據比原始數據略長,為原來的4/3。

文本 M a n
ASCII編碼 77 97 110
二進制位 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
索引 19 22 5 46
Base64編碼 T W F u

     M的Ascii碼是77,前六位對應值為19,對應base64字符是T,如此類推。其它字符編碼就可以自動轉換得到!我們看看另外不是剛好是3個字節的情況!

文本(1 Byte) A    
二進制位 0 1 0 0 0 0 0 1                                
二進制位(補0) 0 1 0 0 0 0 0 1 0 0 0 0                        
Base64編碼 Q Q = =
文本(2 Byte) B C  
二進制位 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1     x x x x x x
二進制位(補0) 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 x x x x x x
Base64編碼 Q k M  =

二、Base64轉換代碼實現

 1 public class Base64Util {
 2     private static final char last2byte = (char) Integer.parseInt("00000011", 2);
 3     private static final char last4byte = (char) Integer.parseInt("00001111", 2);
 4     private static final char last6byte = (char) Integer.parseInt("00111111", 2);
 5     private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
 6     private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
 7     private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
 8     private static final char[] encodeTable = new char[]
 9             {
10                     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
11                     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
12                     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
13                     'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
14             };
15 
16     public Base64Util() {
17     }
18 
19     public static String encode(byte[] from) {
20         StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
21         int num = 0;
22         char currentByte = 0;
23 
24         int i;
25         for (i = 0; i < from.length; ++i) {
26             for (num %= 8; num < 8; num += 6) {
27                 switch (num) {
28                     case 0:
29                         currentByte = (char) (from[i] & lead6byte);
30                         currentByte = (char) (currentByte >>> 2);
31                     case 1:
32                     case 3:
33                     case 5:
34                     default:
35                         break;
36                     case 2:
37                         currentByte = (char) (from[i] & last6byte);
38                         break;
39                     case 4:
40                         currentByte = (char) (from[i] & last4byte);
41                         currentByte = (char) (currentByte << 2);
42                         if (i + 1 < from.length) {
43                             currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
44                         }
45                         break;
46                     case 6:
47                         currentByte = (char) (from[i] & last2byte);
48                         currentByte = (char) (currentByte << 4);
49                         if (i + 1 < from.length) {
50                             currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
51                         }
52                 }
53 
54                 to.append(encodeTable[currentByte]);
55             }
56         }
57 
58         if (to.length() % 4 != 0) {
59             for (i = 4 - to.length() % 4; i > 0; --i) {
60                 to.append("=");
61             }
62         }
63 
64         return to.toString();
65     }
66 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM