C++实现BASE64编码及解码

//<cpp-begin>和<cpp-end>之间为BASE64.cpp的完整内容.BASE64.h文件中仅包含函数原型,不包含其他任何内容.

//<cpp-begin>

//BASE64,v1.0.001
//base64加密解密模块
//updated:2024-04-23
//
#include "BASE64.h"

#ifndef NULL
#define NULL 0
#endif

static const char    BASE64_CHARSA[] =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";//base64编码字符表(ANSI)
char    BASE64_FILLUPA = '=';//填充字符

typedef union base64_value
{
    unsigned long value;
    unsigned char bytes[4];
}BASE64_VALUE;

//编码函数
/************************************************************
pstrEncoded:指向密文缓冲区的指针[输出]
ulSize     :申明密文缓冲区可以容纳的最大字节数量(含空中止)
pstrText   :指向明文缓冲区的指针[输入]
返回值:0表示参数错误;其他值为密文的字符数量(不含空中止).
注:
仅当输出缓冲区可以容纳编码后的所有密文时,函数才能完成编码;
否则可能导致输出缓冲区内容被修改且不是想要的结果;
************************************************************/
unsigned long BASE64_EncodedA(char * pstrEncoded, unsigned long ulSize, const char * pstrText)
{
    unsigned long ulLenOfText = 0;
    unsigned long ulLenOfEncoded = 0;
    unsigned long i = 0;
    unsigned char ucChar = 0, ucPiece = 0;
    BASE64_VALUE sValue = { 0 };
    BASE64_VALUE * psEncoded = (BASE64_VALUE*)pstrEncoded;
    //基本参数检查,不允许明文指针为空
    if (NULL == pstrText)    return 0;
    //统计明文的字符数量
    while (0 != pstrText[ulLenOfText])
    {
        ulLenOfText++;
    }
    //基本参数检查,不允许明文长度为零.
    if (0 == ulLenOfText)    return 0;
    //对明文进行编码,每3字节明文转换成4字节编码文本,不足3字节的部分补充“填充符”.
    for (i = 0; i < ulLenOfText; i++)
    {
        ucPiece = i % 3;
        sValue.bytes[2 - ucPiece] = pstrText[i];//Intel系列的内存字节顺序为低端序
        //sValue.bytes[ucPiece] = pstrText[i];//高端序(不使用,仅作为备注参考)
        if ((ulLenOfText - 1) == i || 2 == ucPiece)
        {//到达原文本结尾处,或,已经取出了3个字符
            if (NULL != psEncoded && (ulLenOfEncoded + 4) < ulSize)
            {    //输出缓冲区不为空,且,当前即将操作的位置没有超过最大长度限制;
                //满足条件时才会输出密文,否则仅计算输出缓冲区需要的空间;
                //明文3字节共24位,按顺序拆分成4个6位.
                //1st byte of encoded;
                ucChar = (unsigned char)((sValue.value << 8) >> 26);
                psEncoded->bytes[0] = BASE64_CHARSA[ucChar];
                //2nd byte of encoded
                ucChar = (unsigned char)((sValue.value << 14) >> 26);
                psEncoded->bytes[1] = BASE64_CHARSA[ucChar];
                //3th byte of encoded
                ucChar = (unsigned char)((sValue.value << 20) >> 26);
                psEncoded->bytes[2] = BASE64_CHARSA[ucChar];
                //4th byte of encoded
                ucChar = (unsigned char)((sValue.value << 26) >> 26);
                psEncoded->bytes[3] = BASE64_CHARSA[ucChar];
                //检查是否需要补充填充字符
                if (1 == ucPiece)//需要补充1个填充字符
                {
                    psEncoded->bytes[3] = BASE64_FILLUPA;
                }
                if (0 == ucPiece)//需要补充2个填充字符
                {
                    psEncoded->bytes[2] = BASE64_FILLUPA;
                    psEncoded->bytes[3] = BASE64_FILLUPA;
                }
                psEncoded++;
            }
            ulLenOfEncoded += 4;
            sValue.value = 0;//重置(必要操作,当明文长度不是3的整数倍时会导致值异常).
        }
    }
    if(NULL != psEncoded)    psEncoded->bytes[0] = 0;//补充空中止
    return ulLenOfEncoded;
}

//解码函数
/************************************************************
pstrText   :指向明文缓冲区的指针[输出]
ulSize     :申明明文缓冲区可以容纳的最大字节数量(含空中止)
pstrEncoded:指向密文缓冲区的指针[输入]
返回值:0表示参数错误;其他值为明文的字符数量(不含空中止).
注:
仅当输出缓冲区可以容纳解码后的所有明文时,函数才能完成解码;
否则可能导致输出缓冲区内容被修改且不是想要的结果;
************************************************************/
unsigned long BASE64_DecodedA(char * pstrText, unsigned long ulSize, const char * pstrEncoded)
{
    unsigned long ulLenOfText = 0;
    unsigned long ulLenOfEncoded = 0;
    unsigned long ulIndex = 0;
    unsigned long i = 0;
    unsigned char j = 0;
    BASE64_VALUE sValue = { 0 };
    unsigned char cChar = 0, ucPiece = 0;
    //基本参数检查,不允许密文指针为空
    if (NULL == pstrEncoded)    return 0;
    //统计密文长度
    while (0 != pstrEncoded[ulLenOfEncoded])
    {
        ulLenOfEncoded++;
    }
    //密文长度不能为零值,且必须是4的整数倍.
    if (0 == ulLenOfEncoded || 0 != (ulLenOfEncoded % 4))    return 0;
    //对密文进行解码,每4字节密文转换成3字节明文
    for (i = 0; i < ulLenOfEncoded; i++)
    {
        ucPiece = i % 4;
        sValue.bytes[ucPiece] = pstrEncoded[i];
        //由密文字符转换成索引值
        for (j = 0; j < 64; j++)
        {
            if (BASE64_CHARSA[j] == sValue.bytes[ucPiece])
            {
                sValue.bytes[ucPiece] = j;
                break;
            }
        }
        if (j == 64)    sValue.bytes[ucPiece] = 0;//填充符(或非法字符)处理
        if ((ulLenOfEncoded - 1) == i || 3 == ucPiece)
        {//到达密文结尾处,或,已取出4字节
            if (NULL != pstrText && (ulLenOfText + 3) < ulSize)
            {    //输出缓冲区不为空,且,当前即将操作的位置没有超过最大长度限制;
                //[密文]1~4字节中仅后6位是需要的字节位,共24位(即转换后的3字节);
                //取值顺序同编码函数,采用高端序字节顺序进行解码;
                //位操作比乘法快,所以采用位操作来计算需要的结果.
                //[密文]第4字节的345678位组成明文第3字节的低6位,[密文]第3字节的78位组成明文第3字节的高2位.
                cChar = ((sValue.bytes[3] << 2) >> 2 ) | (sValue.bytes[2] << 6 );
                pstrText[ulLenOfText + 2] = cChar;
                //[密文]第3字节的3456位组成明文第2字节的低4位,[密文]第2字节的5678位组成明文第2字节的高4位.
                cChar = ((sValue.bytes[2] << 2) >> 4) | (sValue.bytes[1] << 4);
                pstrText[ulLenOfText + 1] = cChar;
                //[密文]第2字节的34位组成明文第1字节的低2位,[密文]第1字节的345678位组成明文第1字节的高6位.
                cChar = (sValue.bytes[1] >> 4) | (sValue.bytes[0] << 2);
                pstrText[ulLenOfText + 0] = cChar;
            }
            ulLenOfText += 3;
            //sValue.value = 0;//重置(非必要操作,密文长度限定为4的整数倍);
        }
    }
    if (NULL != pstrText)    pstrText[ulLenOfText] = 0;//补充空中止
    return ulLenOfText;
}
//<cpp-end>

用法简单:

#include <iostream>
using namespace std;

#include "BASE64.h"

void main()
{
    char strOut[1024] = { 0 };
    char strOut2[1024] = { 0 };
    Str_CopyA(strOut, "thisisatesttext...");//复制一串文本,用于验证空中止设置正确与否;
    cout << "len:" << BASE64_EncodedA(strOut, 1024, "Username:") << endl;
    cout << "encoded<" << strOut << ">" << endl;

    Str_CopyA(strOut2, "thisisatesttext...");//复制一串文本,用于验证空中止设置正确与否;
    cout << "len:" << BASE64_DecodedA(strOut2, 1024, strOut) << endl;
    cout << "decoded<" << strOut2 << ">" << endl;
}

  • 32
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是一个简单的Base64编码解码实现的C程序: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> const char BASE64_TABLE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char* base64_encode(const unsigned char* data, size_t input_length) { size_t output_length = 4 * ((input_length + 2) / 3); char* encoded_data = malloc(output_length + 1); if (encoded_data == NULL) return NULL; for (size_t i = 0, j = 0; i < input_length;) { uint32_t octet_a = i < input_length ? data[i++] : 0; uint32_t octet_b = i < input_length ? data[i++] : 0; uint32_t octet_c = i < input_length ? data[i++] : 0; uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; encoded_data[j++] = BASE64_TABLE[(triple >> 3 * 6) & 0x3F]; encoded_data[j++] = BASE64_TABLE[(triple >> 2 * 6) & 0x3F]; encoded_data[j++] = BASE64_TABLE[(triple >> 1 * 6) & 0x3F]; encoded_data[j++] = BASE64_TABLE[(triple >> 0 * 6) & 0x3F]; } for (size_t i = 0; i < input_length % 3; i++) { encoded_data[output_length - 1 - i] = '='; } encoded_data[output_length] = '\0'; return encoded_data; } unsigned char* base64_decode(const char* data, size_t input_length, size_t* output_length) { if (input_length % 4 != 0) return NULL; *output_length = input_length / 4 * 3; if (data[input_length - 1] == '=') (*output_length)--; if (data[input_length - 2] == '=') (*output_length)--; unsigned char* decoded_data = malloc(*output_length); if (decoded_data == NULL) return NULL; for (size_t i = 0, j = 0; i < input_length;) { uint32_t sextet_a = data[i] == '=' ? 0 & i++ : BASE64_TABLE[data[i++]]; uint32_t sextet_b = data[i] == '=' ? 0 & i++ : BASE64_TABLE[data[i++]]; uint32_t sextet_c = data[i] == '=' ? 0 & i++ : BASE64_TABLE[data[i++]]; uint32_t sextet_d = data[i] == '=' ? 0 & i++ : BASE64_TABLE[data[i++]]; uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; } return decoded_data; } int main() { const char* input = "Hello, world!"; size_t input_length = strlen(input); char* encoded_data = base64_encode((const unsigned char*)input, input_length); printf("Encoded data: %s\n", encoded_data); size_t output_length; unsigned char* decoded_data = base64_decode(encoded_data, strlen(encoded_data), &output_length); printf("Decoded data: %s\n", decoded_data); free(encoded_data); free(decoded_data); return 0; } ``` 程序首先定义了一个Base64字符表,包含了所有可能的Base64字符。然后实现了两个函数,分别是Base64编码解码函数。 Base64编码函数将输入数据按照每3个字节一组进行处理,将每组字节转换成4个Base64字符。如果输入数据不是3的倍数,则在末尾加上相应数量的0字节,以使其能够被3整除。最后,函数将转换后的字符串末尾补上相应数量的=字符。 Base64解码函数将输入数据按照每4个字符一组进行处理,将每组字符转换成3个字节。如果末尾有=字符,则说明输入数据被填充了,需要在解码后去掉填充的0字节。 在程序中,我们将一个字符串进行Base64编码,然后再将编码后的字符串解码回原始字符串,最后输出结果。在输出解码后的数据时,我们将其当作一个字符串输出,可能会出现乱码,这是因为转换后的数据可能包含了0字节,而字符串输出函数会在遇到0字节时停止输出。如果需要输出二进制数据,应该使用fwrite函数来输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值