Base64編碼

晖_IL發表於2024-06-13

Base64編碼

Base64是一種基於64個可列印字元來表示二進位制資料的表示方法。由於2的6次方等於64,所以每6個位元為一個單元,對應某個可列印字元。3個位元組有24個位元,對應於4個Base64單元,即3個位元組可由4個可列印字元來表示。它可用來作為電子郵件的傳輸編碼。在Base64中的可列印字元包括字母A-Z、a-z、數字0-9,這樣共有62個字元,此外兩個可列印符號在不同的系統中而不同

Base64演算法,ASCII碼字串 -- Base64編碼("0-9",“A-Z”,"a-z", '+')

https://img-blog.csdnimg.cn/20190304150859716.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE5NzgyMDE5,size_16,color_FFFFFF,t_70

需要把3個位元組轉換為4部分

xxxx xxxx | xxxx xxxx | xxxx xxxx

https://img-blog.csdnimg.cn/20190304154055574.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE5NzgyMDE5,size_16,color_FFFFFF,t_70

24位字串:“010011010110000101101110”的第一組6位數是“010011”,對應的十進位制數是19,我們查詢索引表發現,19對應的字元是“T”,因此,第一組6位數對應的字元就是“T”;同理,第二組6位數是“010110”,對應的十進位制數是22,查詢索引表,22對應的字元是“W”;同理,第三組6位數是“000101”,對應的十進位制是5,查表得,5對應的字元是“F”;同理,第四組6位數是“101110”,對應的十進位制是46,查表得,46對應的字元是“F”。到此,3個ASCII字元,一共24位,最後編碼成了4個ASCII字元,32位。因此,從24位到32位的轉變,使得Base64編碼的結果要比原來的值變得更大,且大1/3。因此,Base64編碼實質上就是把一個個24位元位組成的二進位制組合轉換成32位元位組成的二進位制組合。

Base64常用於在通常處理文字[資料]的場合,表示、傳輸、儲存一些二進位制資料,包括MIME電子郵件XML的一些複雜資料。

https://img-blog.csdnimg.cn/20190304161336383.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE5NzgyMDE5,size_16,color_FFFFFF,t_70

編碼部分

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Base64字元對映表
static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// Base64編碼函式
char *base64_encode(const unsigned char *input, int length) {
    // 計算編碼後的長度,4 * ((length + 2) / 3) 確保每三個位元組編碼成四個字元
    int enc_len = 4 * ((length + 2) / 3);
    char *encoded = (char *)malloc(enc_len + 1); // 為編碼後的字串分配記憶體
    if (!encoded) {
        return NULL; // 如果記憶體分配失敗,返回NULL
    }

    int i = 0, j = 0;
    unsigned char char_array_3[3], char_array_4[4];

    // 迴圈遍歷輸入資料
    while (length--) {
        char_array_3[i++] = *(input++); // 將輸入資料分成3位元組一組
        if (i == 3) {
            // 將3位元組資料編碼成4個Base64字元
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; i < 4; i++) {
                encoded[j++] = base64_chars[char_array_4[i]]; // 對映Base64字元
            }
            i = 0;
        }
    }

    // 處理剩餘的位元組
    if (i) {
        for (int k = i; k < 3; k++) {
            char_array_3[k] = '\0';
        }

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (int k = 0; k < i + 1; k++) {
            encoded[j++] = base64_chars[char_array_4[k]];
        }

        while (i++ < 3) {
            encoded[j++] = '=';
        }
    }

    encoded[j] = '\0'; // 新增字串結束符
    return encoded;
}

解碼部分

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Base64字元對映表
static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// 獲取Base64字元對應的值
static int base64_char_value(char c) {
    if (c >= 'A' && c <= 'Z') return c - 'A';
    if (c >= 'a' && c <= 'z') return c - 'a' + 26;
    if (c >= '0' && c <= '9') return c - '0' + 52;
    if (c == '+') return 62;
    if (c == '/') return 63;
    return -1;
}

// Base64解碼函式
unsigned char *base64_decode(const char *input, int *output_length) {
    int length = strlen(input);
    int i = 0, j = 0, in = 0;
    int dec_len = length / 4 * 3; // 計算解碼後的長度
    unsigned char *decoded = (unsigned char *)malloc(dec_len); // 為解碼後的資料分配記憶體
    if (!decoded) {
        return NULL; // 如果記憶體分配失敗,返回NULL
    }

    unsigned char char_array_4[4], char_array_3[3];

    // 迴圈遍歷輸入資料
    while (length-- && (input[in] != '=') && (base64_char_value(input[in]) != -1)) {
        char_array_4[i++] = input[in++];
        if (i == 4) {
            for (i = 0; i < 4; i++) {
                char_array_4[i] = base64_char_value(char_array_4[i]);
            }

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (i = 0; (i < 3); i++) {
                decoded[j++] = char_array_3[i]; // 將4個Base64字元解碼成3位元組資料
            }
            i = 0;
        }
    }

    // 處理剩餘的字元
    if (i) {
        for (int k = i; k < 4; k++) {
            char_array_4[k] = 0;
        }

        for (int k = 0; k < 4; k++) {
            char_array_4[k] = base64_char_value(char_array_4[k]);
        }

        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

        for (int k = 0; (k < i - 1); k++) {
            decoded[j++] = char_array_3[k];
        }
    }

    *output_length = j; // 設定解碼後的長度
    return decoded;
}

僅用於學習記錄

參考:

什麼是Base64演算法?——全網最詳細講解-CSDN部落格

相關文章