Base64 编码和解码将每 3 个字节的数据编码为 4 个 ASCII 字符,这样可以确保数据在文本环境中以安全的方式传输。编码后的结果包含字母、数字、加号 (+)、斜线 (/),以及用于填充的等号 (=)。C语言 标准库本身并没有提供 Base64 编码和解码的函数,但是可以使用一些开源的库,或者自己实现编码和解码的算法。

1、使用开源库(如 OpenSSL)

OpenSSL 库提供了一个易于使用的 API 来进行 Base64 编解码。如未安装,Linux 中,通常可以通过包管理器安装 OpenSSL。

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>

// 编码函数
char *base64_encode(const unsigned char *input, int length) {
    int encoded_length = 4 * ((length + 2) / 3);  // Base64 编码输出的长度
    char *encoded = malloc(encoded_length + 1);  // 包含结束符 '\0'
    EVP_EncodeBlock((unsigned char*)encoded, input, length);
    return encoded;
}

// 解码函数
unsigned char *base64_decode(const char *input, int *length) {
    int decoded_length = (strlen(input) * 3) / 4;
    unsigned char *decoded = malloc(decoded_length);
    *length = EVP_DecodeBlock(decoded, (unsigned char*)input, strlen(input));
    return decoded;
}

int main() {
    // 示例:Base64 编码
    unsigned char input[] = "Hello, World!";
    int input_length = strlen((char *)input);

    // 编码
    char *encoded = base64_encode(input, input_length);
    printf("Encoded: %s\n", encoded);

    // 解码
    int decoded_length;
    unsigned char *decoded = base64_decode(encoded, &decoded_length);
    printf("Decoded: %.*s\n", decoded_length, decoded);

    // 释放内存
    free(encoded);
    free(decoded);

    return 0;
}

2、自定义实现 Base64 编码和解码

如果不想依赖外部库,可以使用一个简单的 Base64 编码和解码函数。

1)Base64 编码

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

static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// 编码函数
char* base64_encode(const unsigned char *input, int length) {
    int encoded_length = 4 * ((length + 2) / 3);  // 计算编码后的长度
    char *encoded = malloc(encoded_length + 1);  // +1 用于 '\0' 结尾
    int i, j = 0;
    unsigned char temp[3];

    for (i = 0; i < length;) {
        temp[0] = input[i++];
        temp[1] = (i < length) ? input[i++] : 0;
        temp[2] = (i < length) ? input[i++] : 0;

        encoded[j++] = base64_table[temp[0] >> 2];
        encoded[j++] = base64_table[((temp[0] & 0x03) << 4) | (temp[1] >> 4)];
        encoded[j++] = (i > length + 1) ? '=' : base64_table[((temp[1] & 0x0F) << 2) | (temp[2] >> 6)];
        encoded[j++] = (i > length) ? '=' : base64_table[temp[2] & 0x3F];
    }
    encoded[j] = '\0';
    return encoded;
}

2)Base64 解码

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

static const int base64_decode_table[256] = {
    // 非 Base64 字符都映射为 -1
    // 用于解码的字符集
    // 'A'-'Z': 0-25, 'a'-'z': 26-51, '0'-'9': 52-61, '+' = 62, '/' = 63, '=' = -1
    ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7, ['I'] = 8, ['J'] = 9, 
    ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, 
    ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24, ['Z'] = 25, 
    ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, 
    ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, 
    ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, 
    ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, 
    ['+'] = 62, ['/'] = 63
};

// 解码函数
unsigned char* base64_decode(const char* input, int* length) {
    int len = strlen(input);
    int output_length = len * 3 / 4;
    unsigned char *decoded = malloc(output_length);
    int i, j = 0;
    unsigned char temp[4];
    
    for (i = 0; i < len; i += 4) {
        temp[0] = base64_decode_table[(unsigned char)input[i]];
        temp[1] = base64_decode_table[(unsigned char)input[i+1]];
        temp[2] = base64_decode_table[(unsigned char)input[i+2]];
        temp[3] = base64_decode_table[(unsigned char)input[i+3]];

        decoded[j++] = (temp[0] << 2) | (temp[1] >> 4);
        decoded[j++] = (temp[1] << 4) | (temp[2] >> 2);
        decoded[j++] = (temp[2] << 6) | temp[3];
    }

    *length = j; // 返回解码后的数据长度
    return decoded;
}

3)完整示例

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

static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// 编码函数
char* base64_encode(const unsigned char *input, int length) {
    int encoded_length = 4 * ((length + 2) / 3);  // 计算编码后的长度
    char *encoded = malloc(encoded_length + 1);  // +1 用于 '\0' 结尾
    int i, j = 0;
    unsigned char temp[3];

    for (i = 0; i < length;) {
        temp[0] = input[i++];
        temp[1] = (i < length) ? input[i++] : 0;
        temp[2] = (i < length) ? input[i++] : 0;

        encoded[j++] = base64_table[temp[0] >> 2];
        encoded[j++] = base64_table[((temp[0] & 0x03) << 4) | (temp[1] >> 4)];
        encoded[j++] = (i > length + 1) ? '=' : base64_table[((temp[1] & 0x0F) << 2) | (temp[2] >> 6)];
        encoded[j++] = (i > length) ? '=' : base64_table[temp[2] & 0x3F];
    }
    encoded[j] = '\0';
    return encoded;
}


static const int base64_decode_table[256] = {
    // 非 Base64 字符都映射为 -1
    // 用于解码的字符集
    // 'A'-'Z': 0-25, 'a'-'z': 26-51, '0'-'9': 52-61, '+' = 62, '/' = 63, '=' = -1
    ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7, ['I'] = 8, ['J'] = 9, 
    ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, 
    ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24, ['Z'] = 25, 
    ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, 
    ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, 
    ['u'] = 46, ['v'] = 47, ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, 
    ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, 
    ['+'] = 62, ['/'] = 63
};

// 解码函数
unsigned char* base64_decode(const char* input, int* length) {
    int len = strlen(input);
    int output_length = len * 3 / 4;
    unsigned char *decoded = malloc(output_length);
    int i, j = 0;
    unsigned char temp[4];
    
    for (i = 0; i < len; i += 4) {
        temp[0] = base64_decode_table[(unsigned char)input[i]];
        temp[1] = base64_decode_table[(unsigned char)input[i+1]];
        temp[2] = base64_decode_table[(unsigned char)input[i+2]];
        temp[3] = base64_decode_table[(unsigned char)input[i+3]];

        decoded[j++] = (temp[0] << 2) | (temp[1] >> 4);
        decoded[j++] = (temp[1] << 4) | (temp[2] >> 2);
        decoded[j++] = (temp[2] << 6) | temp[3];
    }

    *length = j; // 返回解码后的数据长度
    return decoded;
}

int main() {
    const unsigned char input[] = "Hello, World!";
    int input_len = strlen((const char *)input);

    // 编码
    char *encoded = base64_encode(input, input_len);
    printf("Encoded: %s\n", encoded);

    // 解码
    int decoded_len;
    unsigned char *decoded = base64_decode(encoded, &decoded_len);
    printf("Decoded: %.*s\n", decoded_len, decoded);

    // 释放内存
    free(encoded);
    free(decoded);

    return 0;
}