Java加密解密(二) Base64編碼

來源:互聯網
上載者:User

標籤:

1. Base64的由來

Base64最早用於解決電子郵件傳輸問題。由於“曆史問題”,早期的電子郵件網關只允許傳輸ASCII(二進位為00000000-01111111)字元,如果有非ASCII字元經過這種網關時, 字元的二進位位可能會被篡改(如將10000001改為00000001)。由此產生了Base64編碼來保證非ASCII字元的傳輸。

2. 原理

Base64顧名思義是一種基於64個字元的編碼演算法。
如下是Base64的字元對應表,詳情參見RFC 2045

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

其中的value是10進位的值,Encoding是與之相對應的編碼字元

因為Base64中共有64個字元,所以只需要6個bit就可以表示一個base64字元(*1<<6=64*)。另外,由於電腦基本處理單位為位元組,所以字元編碼是以位元組為單位對字元進行編碼,比如,字元’A’的ASCII編碼為01000001,漢字’你’的UTF-8編碼為11100100 10111101 10100000, GBK編碼為11000100 11100011。由此,Base64的編碼步驟如下:
step1 將待轉碼字串以某種編碼格式(如UTF-8)進行編碼,得到一個位元組數組
step2 將位元組數組按三個位元組為一組進行分組(24個bit)
step3 將每個分組按6 bit進行劃分(不足6位時低位補0),得到N(*2<=N<=4*)個6位二進位碼(以下稱為Base64編碼單元)。
step4 將每個Base64編碼單元轉換為10進位值,並根據上表得到相應的Base64編碼字元,不足4個編碼單元的分組要用=進行填充。

Base64編碼過程樣本 -
原始字串 我x
UTF-8編碼,分組 0xe6 0x88 0x91; 0x78
二進位表示 11100110, 10001000, 10010001; 01111000
劃分編碼單元 111001,101000,100010,010001; 011110,0000000(補位)
Value 57,40,34,17; 30,0
對應Encoding 5,o,i,R; e,A, =,=(填充符)
最終結果 5oiReA==
3. 用途

1) 儲存位元據,如密鑰等。
2) 使用Http協議在url中傳輸位元據。
將Base64編碼中不符合URL規定的字元替換成其他合法的字元,並去掉斷行符號換行就得到了UrlBase64編碼。經過UrlBase64編碼,就可以將二進位參數直接放在url中。
這些功能也可以用hex編碼實現,但base64編碼的結果要比hex結果短。

4. 實現

jdk中的類sun.misc.BASE64Encodersun.misc.BASE64Decoder提供了Base64的編碼解碼實現,但jdk中sun開頭的包是sun公司的內部實現,該包下的代碼不保證與其他jave平台的相容性(見Why Developers Should Not Write Programs That Call ‘sun’ Packages),所以需要使用第三方實現,也可將這兩個類複製到自己的代碼中。
筆者測試環境中使用的maven依賴如下:


<!--bouncycastle依賴--> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk16</artifactId> <version>1.46</version> </dependency> <!--commons-codec--> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>

4.1 BouncyCastle實現

org.bouncycastle.util.encoders下提供了工具類Base64,UrlBase64與Hex用於Base64,UrlBase64與hex編碼/解碼操作。


final String charset="UTF-8";String input="Base64編/解碼";//編碼String encoded=new String(Base64.encode(input.getBytes(charset)),"ASCII");String urlSafeEncoded=new String(UrlBase64.encode(input.getBytes(charset)),"ASCII");//解碼Assert.assertEquals(input,new String(Base64.decode(encoded),charset));Assert.assertEquals(input,new String(UrlBase64.decode(urlSafeEncoded),charset));

4.2 commons-codec實現

工具類org.apache.commons.codec.binary.Base64提供了Base64與UrlBase64的編碼解碼方法。


final String charset="UTF-8";String input="Base64編/解碼";String encoded= Base64.encodeBase64String(input.getBytes(charset));String urlSafeEncoded=Base64.encodeBase64URLSafeString(input.getBytes(charset));Assert.assertEquals(input, new String(Base64.decodeBase64(encoded), charset));Assert.assertEquals(input, new String(Base64.decodeBase64(urlSafeEncoded), charset));

4.3 BouncyCastle與commons-codec區別

標準Base64編碼後的字串每76個字元為一行(稱為分塊),行尾要添加一個斷行符號分行符號“\r\n”。但bouncycastle並沒有這樣做,而commons-codec支援標準實現,但預設並沒有使用。

++++++++++++ BouncyCastle commons-codec
標準(分塊)編碼 不支援 Base64.encodeBase64ChunkedBase64.encodeBase64(binaryData, true)
UrlBase64 沒有斷行符號換行,‘+’變為’-‘, ’/‘變為’_‘, ’=‘變為’.’ 與bouncyCastle相同,但去掉了填充符

Java加密解密(二) Base64編碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.