1. 程式人生 > >Base64演算法、Base64Encode、UrlEcode編碼及應用

Base64演算法、Base64Encode、UrlEcode編碼及應用

本文的主要內容:
1、Base64演算法的由來與定義
2、Base64演算法的原理
3、Base64編碼與urlEncode編碼的區別以及運用場景
4、程式碼例項(注意是否是遵循RFC2048)

Base64演算法的由來

Base64演算法最早應用於解決電子郵件傳輸問題,在早期,電子郵件只支援ASCII碼字元。如果要傳輸一封帶有非ASCII碼字元的電子郵件,當它經過部分閘道器時就可能出現問題,這個閘道器可能會對非ASCII碼字元的二進位制位進行調整,即將這個非ASCII碼的8位二進位制碼最高位置設定為0,此時使用者收到的這個郵件就會是一封亂碼的了。基於這個原因產生了Base64演算法。

Base64是一種基於64個字元的編碼演算法。經過Base編碼後的資料會比原始資料略長,為原來的4/3。經過Base64編碼的字串的字元數是以4為單位的整數倍。

RFC2045規定,在電子郵件中,每行為76個字元,每行末尾新增一個回車換行符(“\r\n”),無論每行是否夠76個字元,都要加一個回車換行符。但實際情況中往往要忽略這一點。

我經常聽到有人說Base64加密,聽著十分變扭。準確地說,Base64是一種編碼。

Base64演算法的原理

在RFC2045中規定的字元對映表:
這裡寫圖片描述

這張字元對映表中,Value指的是十進位制編碼,Encoding指的是字元,共映射了64個字元,這也是Base64演算法命名的來源。對映表的最後一個字元是等號,它是用來補位的。
為了能在HTTP請求中以GET方式傳遞二進位制數,由Base64演算法衍生出了Url Base64演算法。Url Base64主要是替換了Base64字元對映表中的第62、63個字元,也就是將”+”和”/”符號用”-“和”_”代替。至於”=”在Bouncy Castle提供者使用的是”.”代替,而在Commons Codec裡則是完全杜絕使用補位符。

Base64演算法主要是將給定的字元以及字元編碼(如ASCII碼、UTF-8碼)對應的十進位制數為基準,做編碼操作:

  1. 將給定的字串以字元為單位,轉換成對應的字元編碼(如ASCII碼)
  2. 將字元編碼轉換成二進位制
  3. 將二進位制碼進行分組轉換操作,每3個8位二進位制碼為一組,轉換為每4個6位二進位制碼為一組(不足6位時低位補0)。這是一個分組變化的過程,3個8位二進位制碼和4個6為二進位制碼的長度都是24位
  4. 將獲得的4-6二進位制碼組進行補位,向6位二進位制碼高位補2個0,組成4個8位二進位制碼
  5. 將獲得的4-8二進位制碼組轉換為十進位制碼
  6. 將獲得的十進位制碼轉換成Base64字元表中對應的字元
例子1
:假設場景,我們需要對"A"進行Base64編碼,操作如下: 字元============================A ASCII編碼======================65 二進位制碼=======================01000001 4-6二進位制碼====================010000 010000(不足6位,低位補0) 4-8二進位制碼====================00010000 00010000 十進位制碼======================16 16 字元對映表====================Q Q = =

最終獲得是”QQ==”出現2個補位的原因,是我們要滿足,Base64編碼出來的串必須是4的整數倍,不夠就補。此處,源二進位制碼為01000001不足24位,導致4-8二進位制碼組不足4個。我們這裡可以通過一個簡單的方法判斷是否需要補位:

餘數=原文位元組數 MOD 3

  • 餘數=0,不需要補位
  • 餘數=1,補2個等號
  • 餘數=2,補1個等號
例子2:解決非ASCII碼字元編碼的傳輸問題
字元 =========================================== 密
UTF-8碼                  -27                             -81                         -122
二進位制碼            11100101                  10101111                10000110
4-6二進位制碼         111001                    011010                  111110                 000110              
4-8二進位制碼         00111001                  00011010                00111110               00000110
十進位制碼            57                        26                      62                     6
字元對映            5                         a                       +                      G 
字串"密"經過Base64加密得到字串"5a+G",當然,使用GBK編碼的"密"就不是這個結果了。

Base64編碼與urlEncode編碼的區別

UrlEncode

 - `POST`請求中URLEncode和URLDecode用於完成普通字串和
   `application/x-www-from-urlencoded MIME`字符串之間的相互轉化。
 - `GET`請求中字串資料以url的形式傳遞給web伺服器時,字串中是不允許出現空格和特殊字元的。

UrlEncode的過程:

URL_ENCODE的過程就是把URL作為字元按照某種編碼方式(GBK, UTF-8等)編碼成二進位制的位元組碼,然後每個位元組用一個包含3個字元的字串 “%xy” 表示,其中xy為該位元組的兩位十六進位制表示形式。

URL 只能使用 ASCII 字符集來通過因特網進行傳送。除了 -_. 等規定之外的所有非字母數字字元都將被替換成百分號(%)後跟兩位十六進位制數,空格則編碼為加號(+)主要用於編碼 URL 和安全傳輸URL 。

RFC 1738規定:只有字母和數字[0-9a-zA-Z]、一些特殊符號$-_.+!*'(),[不包括雙引號]、以及某些保留字,才可以不經過編碼直接用於URL。

Base64

 - 電子郵件傳輸:可以進行簡單"加密"且防亂碼
 - 網路資料傳輸:不論是通過`HTTP`的`GET`方式以URL引數傳遞引數,還是通過`POST`方式以資料體傳輸資料,都能發現Base64編碼藏匿其中
 - 金鑰儲存:將金鑰從二進位制表現形式轉換成Base64,這樣可讀性變得更高
 - 數字證書儲存:很多數字證書以Base64方式儲存和傳輸

程式碼例項

public static void main(String[] args) throws Exception{
        String s = "高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+高堂明鏡悲白髮,朝如青絲暮成雪+";
        System.out.println("遵循RFC2048:"+ new String(Base64.encodeBase64(s.getBytes("UTF-8"),true)));
        System.out.println("=================================================================================");
        System.out.println("不遵循RFC2048:"+Base64.encodeBase64String(s.getBytes("UTF-8")));
    }

執行結果:
這裡寫圖片描述

1、遵循RFC2048的,每76個字元進行換行。

2、解碼API和加碼類似。