Base64編碼與解碼


簡介

Base64是網絡上最常見的用於傳輸8Bit字節代碼的編碼方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的詳細規范。Base64編碼可用於在HTTP環境下傳遞較長的標識信息。

原理

Base64加密方式是將三個八位的字節轉化為四個六位的字節(不足八位的高位補00),3*8 = 4*6;,所以base64加密過后的內容比原來的大三分之一;
舉例:加密“ace”,
ace轉化為二進制為:‭01100001‬ ‭01100011‬ ‭01100101‬
轉化為base64的四字節六位:011000 01‬‭0110 0011‬01 100101‬
那因為計算機是一字節八位的存數,所以高位補00后變為:00011000 0001‬‭0110 000011‬01 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;
}

 


免責聲明!

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



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