C/C++ base64编解码实战

这里提供2种base64编解码的实现方式:

  1. 通过纯C语言实现
  2. 基于OpenSSL的内的编解码组件

代码均是个人实战验证过的,可放心使用。

接口头文件

#ifndef GL_BASE64_H
#define GL_BASE64_H

#include 

class GLBase64
{
public:
    static std::string Encode(const std::string& src);
    static std::string Decode(const std::string& src);
};

#endif // !GL_BASE64_H

纯C语言实现cpp文件

#include "GLBase64.h"
#include 
#include 
#include 

static int gl_b64idx(int c) {
    if (c < 26) {
        return c + 'A';
    }
    else if (c < 52) {
        return c - 26 + 'a';
    }
    else if (c < 62) {
        return c - 52 + '0';
    }
    else {
        return c == 62 ? '+' : '/';
    }
}

static int gl_b64rev(int c) {
    if (c >= 'A' && c <= 'Z') {
        return c - 'A';
    }
    else if (c >= 'a' && c <= 'z') {
        return c + 26 - 'a';
    }
    else if (c >= '0' && c <= '9') {
        return c + 52 - '0';
    }
    else if (c == '+') {
        return 62;
    }
    else if (c == '/') {
        return 63;
    }
    else if (c == '=') {
        return 64;
    }
    else {
        return -1;
    }
}

int gl_base64_update(unsigned char ch, char* to, int n) {
    int rem = (n & 3) % 3;
    if (rem == 0) {
        to[n] = (char)gl_b64idx(ch >> 2);
        to[++n] = (char)((ch & 3) << 4);
    }
    else if (rem == 1) {
        to[n] = (char)gl_b64idx(to[n] | (ch >> 4));
        to[++n] = (char)((ch & 15) << 2);
    }
    else {
        to[n] = (char)gl_b64idx(to[n] | (ch >> 6));
        to[++n] = (char)gl_b64idx(ch & 63);
        n++;
    }
    return n;
}

int gl_base64_final(char* to, int n) {
    int saved = n;
    // printf("---[%.*s]\n", n, to);
    if (n & 3) n = gl_base64_update(0, to, n);
    if ((saved & 3) == 2) n--;
    // printf("    %d[%.*s]\n", n, n, to);
    while (n & 3) to[n++] = '=';
    to[n] = '\0';
    return n;
}

int gl_base64_encode(const unsigned char* p, int n, char* to) {
    int i, len = 0;
    for (i = 0; i < n; i++) len = gl_base64_update(p[i], to, len);
    len = gl_base64_final(to, len);
    return len;
}

int gl_base64_decode(const char* src, int n, char* dst) {
    const char* end = src + n;
    int len = 0;
    while (src + 3 < end) {
        int a = gl_b64rev(src[0]), b = gl_b64rev(src[1]), c = gl_b64rev(src[2]),
            d = gl_b64rev(src[3]);
        if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
        dst[len++] = (char)((a << 2) | (b >> 4));
        if (src[2] != '=') {
            dst[len++] = (char)((b << 4) | (c >> 2));
            if (src[3] != '=') dst[len++] = (char)((c << 6) | d);
        }
        src += 4;
    }
    dst[len] = '\0';
    return len;
}

std::string GLBase64::Encode(const std::string& src)
{
    if (src.empty()) return "";

    int len = std::ceil(src.size() / 3.0) * 4 + 1;
    char* dst = new char[len];
    memset(dst, 0, len);

    const unsigned char* pSrc = (const unsigned char*)&src[0];
    gl_base64_encode(pSrc, src.size(), dst);

    std::string result(dst, strlen(dst));
    delete[] dst;

    return result;
}

std::string GLBase64::Decode(const std::string& src)
{
    if (src.empty()) return "";

    size_t iSrcLen = src.size();
    if (iSrcLen % 4 != 0)
    {
        std::cout << "input string error." << std::endl;
        return "";
    }

    size_t len = iSrcLen / 4 * 3;

    char* dst = new char[len + 1];
    memset(dst, 0, len + 1);

    len = gl_base64_decode((const char*)&src[0], iSrcLen, dst);

    std::string result(dst, len);
    delete[] dst;

    return result;
}

注意:

这里的C语言实现是引用了mongoose(cesanta/mongoose: Embedded Web Server (github.com))的实现,他是基于GPL协议的,如果想将我分享的代码用于商业且不想开源,请慎重考虑。

基于OpenSSL的内的编解码组件实现

#include "openssl/bio.h"  
#include "openssl/buffer.h"
#include "openssl/evp.h"  

// base64 编码
std::string GLBase64::Encode(const std::string& buffer)
{
    BUF_MEM* bptr;

    BIO* b64 = BIO_new(BIO_f_base64());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    BIO* bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, buffer.data(), buffer.size());
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);
    BIO_set_close(b64, BIO_NOCLOSE);

    std::string out;
    out.resize(bptr->length);
    memcpy(&out[0], bptr->data, bptr->length);
    BIO_free_all(b64);

    return out;
}

// base64 解码
std::string GLBase64::Decode(const std::string& input)
{
    std::string out;
    out.resize(input.size());

    BIO* b64 = BIO_new(BIO_f_base64());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    BIO* bmem = BIO_new_mem_buf(input.data(), input.size());
    bmem = BIO_push(b64, bmem);
    int len = BIO_read(bmem, &out[0], input.size());
    BIO_free_all(bmem);

    out.resize(len);
    return out;
}

OpenSSL内部封装较好,所以代码比较短。在OpenSSL一统天下的年代,涉及网络安全访问,加解密的业务,没有几个公司是不用的。

如果,我的分享给您带来了帮助,别忘了给博主点赞+评论,大家的支持会促使我为大家分享更多的干货。

你可能感兴趣的:(C++,c++,开发语言)