天天看點

java單向加密算法小結(1)--Base64算法簡單了解java代碼實作原理和應用Base64的應用

  從這一篇起整理一下常見的加密算法以及在java中使用的demo,首先從最簡單的開始.

簡單了解

     Base64嚴格來說并不是一種加密算法,而是一種編碼/解碼的實作方式.

  我們都知道,資料在計算機網絡之間是使用位元組流的方式進行傳遞的,所有的資訊都要最終轉換為0101的二進制,這本身就涉及到編碼,解碼的應用.

  Base64,顧名思義,是使用了64個基本的字元來對任意資料進行編碼的一種實作方式,那既然有Base64,是不是也有Base32,Base16呢? 答案是沒錯,有.

  下面先看一下Base64的編碼表:

java單向加密算法小結(1)--Base64算法簡單了解java代碼實作原理和應用Base64的應用

  由圖可見,Base64使用了26個字母的大小寫,也就是52個字元,再加上10個數字和兩個特殊的"+","/"組成,一共64個字元,其中最後兩個字元選取不一定總是這兩個.

java代碼實作

  首先看代碼,然後再細說Base64實作的原理和應用:

1 package com.wang.encryption;
 2 import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
 3 import sun.misc.BASE64Decoder;
 4 import sun.misc.BASE64Encoder;
 5 import java.io.IOException;
 6 /**
 7  * @author yogo.wang
 8  * @date 2016/11/03-下午3:58.
 9  */
10 public class Base64Test {
11 
12     public static void main(String[] args) throws IOException {
13 
14         String msg="wang";
15         byte[] bys=msg.getBytes("utf-8");
16 
17         /**
18          * 使用BASE64 加密(編碼)
19          */
20         //第一種方式
21         BASE64Encoder base64Encoder=new BASE64Encoder();
22         String s = base64Encoder.encodeBuffer(bys);
23         System.out.println(s);
24         System.out.println("---------------------");
25         //第二種方式
26         String s1 = Base64.encode(bys);
27         System.out.println(s1);
28         System.out.println("---------------------");
29         /**
30          * 使用BASE64 解密(解碼)
31          */
32         //第一種方式
33         BASE64Decoder base64Decoder=new BASE64Decoder();
34         byte[] bys2 = base64Decoder.decodeBuffer(s);
35         System.out.println(new String(bys2));
36         System.out.println("---------------------");
37         //第二種方式
38         byte[] bys3 = Base64.decode(s);
39         System.out.println(new String(bys3));
40 
41 
42     }
43 }      

輸出結果如下:

d2FuZw==

---------------------

wang

原理和應用

  根據代碼,可以看到,字元"wang"通過Base64的編碼轉化成了一個字元串"d2FuZw==",那麼到底内部是怎麼實作的呢?

  Base64使用了64的字元,那麼隻需要6個二進制位就可以表示,但是一個Base64字元是8個二進制位的,即8Bit,也就是說Base64在6Bit的基礎上在左邊加了倆0,所有它的左邊兩位永遠為0.

  我們知道,一個字元是占了8位的,那怎麼用6Bit表示8Bit的數呢,這好辦,因為8和6的最小公倍數是24,那麼,我用4個Base64的字元來表示3個正常的字元就可以了.

  知道了這些,我們就可以來看看"wang"這個字元串是怎麼被編碼成"d2FuZw=="的了.

  第一步:把正常字元轉換為ASCII.

  第二步:把ASCII碼轉為8位2進制

  第三步:每6位2進制數劃為一組

  第四步:将2進制轉為10進制

  第五步:根據Base64編碼表對應找出相應的字元

  對應下面的圖:

java單向加密算法小結(1)--Base64算法簡單了解java代碼實作原理和應用Base64的應用

  因為每三個正常字元,對應四個Base64字元,如果不夠的話,會在後邊補0,這裡的"wang"是4個字元,不是3的整數倍,是以需要補0,那為什麼編碼的結果是"d2FuZw==",而不是"d2FuZwAA"呢? 

  原因其實也很簡單,因為最後兩個AA是沒有實際意義的,并不攜帶有效資訊,為了解碼友善,Base64編碼選擇了使用"="來代替最後的"A",是以就是我們看到的"d2FuZw=="了.

  通過以上的過程我們可以發現,其實Base64是一種編碼方式而非加密方式,因為它的編碼解碼過程是完全可逆的,且不需要額外資訊,你隻要有一張Base64的編碼表就可以了,是以,不要将他用于對資料的加密.

Base64的應用

  說了這麼多,好像還是不太明白這種編碼有什麼必須存在的理由.....

  我們知道在計算機中任何資料都是按ascii碼存儲的,而ascii碼的128~255之間的值是不可見字元。而在網絡上交換資料時,比如說從A地傳到B地,往往要經過多個路由裝置,由于不同的裝置對字元的處理方式有一些不同,這樣那些不可見字元就有可能被處理錯誤,這是不利于傳輸的。是以就先把資料先做一個Base64編碼,統統變成可見字元,這樣出錯的可能性就大降低了(這段來自知乎)。

  不僅如此,比如說我們可以使用HTML來内嵌Base64編碼的圖檔,這樣就避免了不必要的外部資源加載,不過還是要量力而為,這種場景一般适用于尺寸比較小的圖檔,如果是高清圖檔,用這種方式會導緻Base64編碼後的字元串很大,反而影響加載速度.