Base64

Base64

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法

代码实现(C++)

/*
   base64.cpp and base64.h
   base64 encoding and decoding with C++.
   More information at
     https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
   Version: 2.rc.04 (release candidate)
   Copyright (C) 2004-2017, 2020 René Nyffenegger
   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.
   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:
   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.
   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.
   3. This notice may not be removed or altered from any source distribution.
   René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/

/**
 * Base64编解码
 * @file: Base64.cpp
 * @author: rancheng <rc4work@163.com>
 * @date: 2020-11-20
 */
#include "Base64.h"

namespace dev {

static std::string base64Encode(BytesConstRef bs, const char* charSet, char padCh) {
    // 提前分配好内存
    auto len = bs.size();
    std::string ret((len + 2) / 3 * 4, '\0');

    // 每3个字节转换为4个Base64字符,不足的后面补充填充字符
    for (size_t i = 0, off = 0; i < len; i += 3) {
        ret[off++] = charSet[(bs[i] & 0xfc) >> 2];
        if (i + 1 < len) {
            ret[off++] = charSet[((bs[i] & 0x03) << 4) + ((bs[i + 1] & 0xf0) >> 4)];
            if (i + 2 < len) {
                ret[off++] = charSet[((bs[i + 1] & 0x0f) << 2) + ((bs[i + 2] & 0xc0) >> 6)];
                ret[off++] = charSet[bs[i + 2] & 0x3f];
            } else {
                ret[off++] = charSet[(bs[i + 1] & 0x0f) << 2];
                ret[off++] = padCh;
            }
        } else {
            ret[off++] = charSet[(bs[i] & 0x03) << 4];
            ret[off++] = padCh;
            ret[off++] = padCh;
        }
    }

    return ret;
}

// 将字节数组转换为Base64编码的字符串(标准字符集)
std::string toBase64STD(BytesConstRef bs) {
    // 字符集
    static auto s_stdBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                   "abcdefghijklmnopqrstuvwxyz"
                                   "0123456789"
                                   "+/";
    // 填充字符
    static char s_stdPadCh = '=';

    return base64Encode(bs, s_stdBase64Chars, s_stdPadCh);
}

// 将字节数组转换为Base64编码的字符串(对url合法的字符集)
std::string toBase64URL(BytesConstRef bs) {
    // 字符集
    static auto s_urlBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                   "abcdefghijklmnopqrstuvwxyz"
                                   "0123456789"
                                   "-_";
    // 填充字符
    static char s_urlPadCh = '=';

    return base64Encode(bs, s_urlBase64Chars, s_urlPadCh);
}

// base64字符转换为对应的int值(标准字符集)
static int base64Ch2iSTD(int base64Ch) {
    if (base64Ch >= 'A' && base64Ch <= 'Z') return base64Ch - 'A';
    if (base64Ch >= 'a' && base64Ch <= 'z') return base64Ch - 'a' + ('Z' - 'A') + 1;
    if (base64Ch >= '0' && base64Ch <= '9') return base64Ch - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
    if (base64Ch == '+') return 62;
    if (base64Ch == '/') return 63;
    throw BadBase64Ch();
}

// base64字符转换为对应的int值(对url合法的字符集)
static int base64Ch2iURL(int base64Ch) {
    if (base64Ch >= 'A' && base64Ch <= 'Z') return base64Ch - 'A';
    if (base64Ch >= 'a' && base64Ch <= 'z') return base64Ch - 'a' + ('Z' - 'A') + 1;
    if (base64Ch >= '0' && base64Ch <= '9') return base64Ch - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
    if (base64Ch == '-') return 62;
    if (base64Ch == '_') return 63;
    throw BadBase64Ch();
}

using Base64Ch2i = int(*)(int);
Bytes base64Decode(const std::string& base64, Base64Ch2i base64Ch2i, char padCh) {
    // 提前分配内存
    auto len = base64.size();
    Bytes ret((len + 3) / 4 * 3);

    // 每4个Base64字符转换为3个字节
    size_t off = 0;
    for (size_t i = 0; i < len; i += 4) {
        int one = base64Ch2i(base64[i]);
        // C++11标准保证str[str.size()]为'\0'
        int two = base64Ch2i(base64[i + 1]);
        ret[off++] = (one << 2) + ((two & 0x30) >> 4);
        if (base64[i + 2] != padCh) {
            int three = base64Ch2i(base64[i + 2]);
            ret[off++] = ((two & 0x0f) << 4) + ((three & 0x3c) >> 2);
            if (base64[i + 3] != padCh) {
                int four = base64Ch2i(base64[i + 3]);
                ret[off++] = ((three & 0x03) << 6) + four;
            }
        }
    }

    ret.resize(off);
    return ret;
}

/**
 * 将Base64编码的字符串转换为字节数组
 * @param base64 Base64编码的字符串(标准字符集)
 * @return 对应的字节数组
 * @throw 遇到非法Base64字符抛出BadBase64Ch异常
 */
Bytes fromBase64STD(const std::string& base64) {
    // 填充字符
    static char s_stdPadCh = '=';

    return base64Decode(base64, base64Ch2iSTD, s_stdPadCh);
}



/**
 * 将Base64编码的字符串转换为字节数组
 * @param base64 Base64编码的字符串(对url合法的字符集)
 * @return 对应的字节数组
 * @throw 遇到非法Base64字符抛出BadBase64Ch异常
 */
Bytes fromBase64URL(const std::string& base64) {
    // 填充字符
    static char s_urlPadCh = '=';

    return base64Decode(base64, base64Ch2iURL, s_urlPadCh);
}

}   // namespace dev

fromBase64函数中有一个小技巧,那就是在C++11中保证str[str.size()]返回字符'\0'。

URLSafe

Base64编码后的字符,常用来作为URL参数传递。但有些情况下,编码后可能出现字符+和/,在URL中就不能直接作为参数。
一般需要做URL Safe编码,就是把字符+和/分别变成-和_。

posted @   HachikoT  阅读(140)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示