Base64編碼與解碼
阿新 • • 發佈:2022-03-29
簡介
Base64是網路上最常見的用於傳輸8Bit位元組程式碼的編碼方式之一,大家可以檢視RFC2045~RFC2049,上面有MIME的詳細規範。Base64編碼可用於在HTTP環境下傳遞較長的標識資訊。
原理
Base64加密方式是將三個八位的位元組轉化為四個六位的位元組(不足八位的高位補00),3*8 = 4*6;,所以base64加密過後的內容比原來的大三分之一; 舉例:加密“ace”, ace轉化為二進位制為:01100001 01100011 01100101 轉化為base64的四位元組六位:011000 010110 001101 100101 那因為計算機是一位元組八位的存數,所以高位補00後變為:00011000 00010110 00001101 00100101 轉化為十進位制:24 22 13 37 查Base64對照表(預設版本RFC2045): 我們得到最終結果:YWNl 我們觀察這個對照表,大小寫的字母26*2 加上10個數字 加上兩個特殊符號 + / 一共64個字元,因為Base64有效位只有六位,所以最大能表示的字元就為2的6次方64; 例子中為了方便演示我只取了三個位元組的字串,實際中會存在位元組數量不是3倍數的情況,Base64是這樣處理的: 剩餘的位元組根據編碼規則繼續單獨轉(不夠的位數用0補全),再用=號補滿4個位元組。這就是為什麼有些Base64編碼會以一個或兩個等號結束的原因,但等號最多隻有兩個。因為: 一個原位元組至少會變成兩個目標位元組(原位元組八位,目標位元組六位),兩個原位元組至少會變成三個目標位元組; 所以如果餘數為1的話,轉成2個Base64編碼字元,這個時候我們需要補2個等號;如果餘數為2的話,轉成3個Base64編碼字元,這個時候我們需要補1個等號;實現
java
private static final byte ENCODE[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v','w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', }; public static String encode(String str){ byte[] bytes = str.getBytes(); String result1 = Base64.encodeToString(bytes, Base64.DEFAULT); int temp = ((bytes[0] & 0xff) << 16) | ((bytes[1] & 0xff) << 8) | ((bytes[2] & 0xff));int char1 = (temp>>18 & 0x3f); int char2 = (temp>>12 & 0x3f); int char3 = (temp>>6 & 0x3f); int char4 = (temp & 0x3f); String result2 = new String(new byte[]{ENCODE[char1],ENCODE[char2],ENCODE[char3],ENCODE[char4]}); LogUtil.i(result1 +""+result2); return result2; }
C
#include <stdio.h> #include <string.h> // 全域性常量定義 const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const char padding_char = '='; /*編碼程式碼 * const unsigned char * sourcedata, 源陣列 * char * base64 ,碼字儲存 */ int base64_encode(const unsigned char * sourcedata, char * base64) { int i=0, j=0; unsigned char trans_index=0; // 索引是8位,但是高兩位都為0 const int datalength = strlen((const char*)sourcedata); for (; i < datalength; i += 3){ // 每三個一組,進行編碼 // 要編碼的數字的第一個 trans_index = ((sourcedata[i] >> 2) & 0x3f); base64[j++] = base64char[(int)trans_index]; // 第二個 trans_index = ((sourcedata[i] << 4) & 0x30); if (i + 1 < datalength){ trans_index |= ((sourcedata[i + 1] >> 4) & 0x0f); base64[j++] = base64char[(int)trans_index]; }else{ base64[j++] = base64char[(int)trans_index]; base64[j++] = padding_char; base64[j++] = padding_char; break; // 超出總長度,可以直接break } // 第三個 trans_index = ((sourcedata[i + 1] << 2) & 0x3c); if (i + 2 < datalength){ // 有的話需要編碼2個 trans_index |= ((sourcedata[i + 2] >> 6) & 0x03); base64[j++] = base64char[(int)trans_index]; trans_index = sourcedata[i + 2] & 0x3f; base64[j++] = base64char[(int)trans_index]; } else{ base64[j++] = base64char[(int)trans_index]; base64[j++] = padding_char; break; } } base64[j] = '\0'; return 0; }