Base64 编码与解码

       在编程领域,Base64 是一组二进制到文本的编码方案,通过将数据转换为基数为 64 的表示形式,以 ASCII 字符串格式来表示二进制数据(更确切地说,是一系列 8 位字节)。“Base64” 这一术语源自特定的多用途互联网邮件扩展(MIME)内容传输编码。每个非最后的 Base64 数字恰好代表 6 位数据。因此,三个 8 位字节(即总共 24 位)可以由四个 6 位的 Base64 数字来表示。

头文件与命名空间

#include <array>     /// for `std::array`
#include <cassert>   /// for `assert` operations
#include <iostream>  /// for IO operations

引入了三个头文件:

  • <array>:提供 std::array 类型支持。

  • <cassert>:提供断言功能,用于测试代码的正确性。

  • <iostream>:用于输入输出操作。

namespace ciphers {
    namespace base64_encoding {

定义了嵌套命名空间 ciphers::base64_encoding,用于组织 Base64 编码和解码的函数。

Base64 编码表

const std::string chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

定义了一个字符串常量 chars,包含 Base64 编码所需的字符集,按照 RFC4648 标准定义。

Base64 编码函数

std::string base64_encode(const std::string& input) {
    std::string base64_string;

定义了 base64_encode 函数,接收一个 std::string 类型的输入参数 input,返回其 Base64 编码后的字符串。

for (uint32_t i = 0; i < input.size(); i += 3) {

循环遍历输入字符串,每次处理 3 个字节。

char first_byte = input[i];
base64_string.push_back(chars[first_byte >> 2]);

提取第一个字节的前 6 位,并将对应的 Base64 字符添加到结果字符串中。

if (i + 1 < input.size()) {
    char second_byte = input[i + 1];
    base64_string.push_back(
        chars[(((first_byte & 3) << 4) | ((second_byte & 0xF0) >> 4))]);

如果存在第二个字节,提取第一个字节的后 2 位和第二个字节的前 4 位,组合成一个新的 6 位值,并添加对应的 Base64 字符。

if (i + 2 < input.size()) {
    char third_byte = input[i + 2];
    base64_string.push_back(chars[((third_byte & 0xC0) >> 6) |
        ((second_byte & 0x0F) << 2)]);
    base64_string.push_back(chars[(third_byte & 0x3F)]);

如果存在第三个字节,提取第二个字节的后 4 位和第三个字节的前 2 位,组合成一个新的 6 位值,并添加对应的 Base64 字符。然后提取第三个字节的后 6 位,添加对应的 Base64 字符。

else {
    base64_string.push_back(chars[((second_byte & 0x0F) << 2)]);
    base64_string.push_back('=');
}

如果不存在第三个字节,仅处理第二个字节,并添加一个填充字符 =

else {
    base64_string.push_back(chars[((first_byte & 3) << 4)]);
    base64_string.push_back('=');
    base64_string.push_back('=');
}

如果输入字符串的长度不足 3 个字节,处理现有字节并添加两个填充字符 =

辅助函数

uint8_t find_idx(const char c) {
    if (c >= 'A' && c <= 'Z') {
        return c - 'A';
    } else if (c >= 'a' && c <= 'z') {
        return c - 'a' + 26;
    } else if (c >= '0' && c <= '9') {
        return c - '0' + 52;
    } else if (c == '+') {
        return 62;
    } else if (c == '/') {
        return 63;
    }
    return -1;
}

定义了一个辅助函数 find_idx,用于查找字符在 Base64 字符集中的位置。根据字符的类型(大写字母、小写字母、数字、+/),返回其对应的索引值。

Base64 解码函数

std::string base64_decode(const std::string& base64_str) {
    std::string base64_decoded;

定义了 base64_decode 函数,接收一个 Base64 编码的字符串 base64_str,返回解码后的原始数据。

for (uint32_t i = 0; i < base64_str.size(); i += 4) {
    char first_byte = base64_str[i];
    char second_byte = base64_str[i + 1];
    char first_actual_byte = static_cast<char>(
        (find_idx(first_byte) << 2) | ((find_idx(second_byte)) >> 4));
    base64_decoded.push_back(first_actual_byte);

循环遍历 Base64 字符串,每次处理 4 个字符。提取前两个字符的 6 位值,组合成一个 8 位值,并添加到解码结果中。

if (i + 2 < base64_str.size() && base64_str[i + 2] != '=') {
    char third_byte = base64_str[i + 2];
    char second_actual_byte =
        static_cast<char>(((find_idx(second_byte) & 0x0F) << 4) |
            (find_idx(third_byte) >> 2));
    base64_decoded.push_back(second_actual_byte);

如果存在第三个字符且不是填充字符 =,提取第二个和第三个字符的 6 位值,组合成另一个 8 位值,并添加到解码结果中。

if (i + 3 < base64_str.size() && base64_str[i + 3] != '=') {
    char fourth_byte = base64_str[i + 3];
    char third_actual_byte =
        static_cast<char>(((find_idx(third_byte) & 0x03) << 6) |
            find_idx(fourth_byte));
    base64_decoded.push_back(third_actual_byte);
}

如果存在第四个字符且不是填充字符 =,提取第三个和第四个字符的 6 位值,组合成最后一个 8 位值,并添加到解码结果中。

测试函数

static void test() {
    std::string str =
        "To err is human, but to really foul things up you need a computer.";
    std::string base64_str = ciphers::base64_encoding::base64_encode(str);
    std::string verify =
        "VG8gZXJyIGlzIGh1bWFuLCBidXQgdG8gcmVhbGx5IGZvdWwgdGhpbmdzIHVwIHlvdSBuZW"
        "RpIGEgY29tcHV0ZXIu";
    assert(base64_str == verify);
    std::string original_str =
        ciphers::base64_encoding::base64_decode(base64_str);
    assert(original_str == str);

第一个测试案例,对一个普通字符串进行 Base64 编码和解码,验证结果是否与原始字符串一致。

str =
    "Man is distinguished, not only by his reason, but by this singular "
    "passion from other animals, which is a lust of the mind, that by a "
    "perseverance of delight in the continued and indefatigable generation "
    "of knowledge, exceeds the short vehemence of any carnal pleasure.";
base64_str = ciphers::base64_encoding::base64_encode(str);
verify =
    "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS"
    "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBh"
    "IGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodC"
    "BpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25v"
    "d2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbG"
    "Vhc3VyZS4=";
assert(base64_str == verify);
original_str = ciphers::base64_encoding::base64_decode(base64_str);
assert(original_str == str);

第二个测试案例,对一个较长的字符串(来自维基百科)进行 Base64 编码和解码,验证结果是否与原始字符串一致。

主函数

int main() {
    test();  // run self-test implementations
    return 0;
}

主函数调用测试函数 test,运行自我测试以验证 Base64 编码和解码的实现是否正确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值