C++实现BASE64编码及解码(最终)

<cpp-begin>和<cpp-end>之间是cpp文件的完整内容;".h"文件仅包含函数原型,不包含其他任何内容,所以没必要复制上来了。

与之间文章里的代码差别是:

1,编码函数增加了一个参数,用于声明传入的明文长度;解码函数增加了一个参数,用于声明传入的密文的长度;目的是提供对宽字节字符串的支持;

2,解码函数通过固定值的数组来获取密文在编码字符表中的索引值,而不是通过临时变量计算获取,目的是提升解码效率;

测试通过,且不再需要更新代码了,为最终版本;两个函数主体代码偏向于代码及逻辑简洁性,循环执行的代码有少量的效率浪费,使得删除注释后函数的代码极少。

//<cpp-begin>BASE64,v1.1.001
//base64编码及解码模块
//updated:2024-05-06
//
#include "BASE64.h"

#ifndef NULL
#define NULL 0
#endif

//BASE64_INDEX[],仅用于解码,密文的每一个字符对应"base64编码字符表"的索引值;
//a=97,z=122;A=65,Z=90;+=43,/=47;0=48,9=57;= =61;
static const char    BASE64_INDEX[256] = {0/*char is null*/,0,0,0,0,0,0,0,0,0,0/*1-10*/,0,0,0,0,0,0,0,0,0,0/*11-20*/, 0,0,0,0,0,0,0,0,0,0/*21-30*/, 0,0,0,0,0,0,0,0,0,0/*31-40*/, 
0,0,62/* '+' */,0,0,0,63/* '/' *//*41-47*/,
52,53,54,55,56,57,58,59,60,61/*48-57:'0'~'9'*/,
0,0,0,64/* '=' */,0,0,0/*58-64*/,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25/*65-90:'A'-'Z'*/,
0,0,0,0,0,0/*91-96*/,
26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51/*97-122:'a'-'z'*/,
0,0,0,0,0/*123-127*//*128~255,all chars is zero*/};
static const char    BASE64_CHARS[65] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/', '\0' };//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\0";//base64编码字符表
static const char    BASE64_FILLUP = '=';//填充字符

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

//编码函数
/************************************************************
pstrEncoded:指向密文缓冲区的指针[输出]
ulSize     :申明密文缓冲区可以容纳的最大字节数量(含空中止)
pstrText   :指向明文缓冲区的指针[输入]
返回值:0表示参数错误;其他值为密文的字符数量(不含空中止).
注:
仅当输出缓冲区可以容纳编码后的所有密文时,函数才能完成编码;
否则可能导致输出缓冲区内容被修改且不是想要的结果;
************************************************************/
unsigned long BASE64_Encoded(char * pstrEncoded, unsigned long ulSize, const char * pstrText, unsigned long ulLenOfText)
{
    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 || 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_CHARS[ucChar];
                //2nd byte of encoded
                ucChar = (unsigned char)((sValue.value << 14) >> 26);
                psEncoded->bytes[1] = BASE64_CHARS[ucChar];
                //3th byte of encoded
                ucChar = (unsigned char)((sValue.value << 20) >> 26);
                psEncoded->bytes[2] = BASE64_CHARS[ucChar];
                //4th byte of encoded
                ucChar = (unsigned char)((sValue.value << 26) >> 26);
                psEncoded->bytes[3] = BASE64_CHARS[ucChar];
                //检查是否需要补充填充字符
                if (1 == ucPiece)//需要补充1个填充字符
                {
                    psEncoded->bytes[3] = BASE64_FILLUP;
                }
                if (0 == ucPiece)//需要补充2个填充字符
                {
                    psEncoded->bytes[2] = BASE64_FILLUP;
                    psEncoded->bytes[3] = BASE64_FILLUP;
                }
                psEncoded++;
            }
            ulLenOfEncoded += 4;
            sValue.value = 0;//重置(必要操作,当明文长度不是3的整数倍时会导致值异常).
        }
    }
    if(NULL != psEncoded)    psEncoded->bytes[0] = 0;//补充空中止
    return ulLenOfEncoded;
}

//解码函数
/************************************************************
pstrText   :指向明文缓冲区的指针[输出]
ulSize     :申明明文缓冲区可以容纳的最大字节数量(含空中止)
pstrEncoded:指向密文缓冲区的指针[输入]
返回值:0表示参数错误;其他值为明文的字符数量(不含空中止).
注:
仅当输出缓冲区可以容纳解码后的所有明文时,函数才能完成解码;
否则可能导致输出缓冲区内容被修改且不是想要的结果;
************************************************************/
unsigned long BASE64_Decoded(char * pstrText, unsigned long ulSize, const char * pstrEncoded, unsigned long ulLenOfEncoded)
{
    BASE64_VALUE sValue = { 0 };
    unsigned long ulLenOfText = 0;
    unsigned long i = 0;
    unsigned char ucPiece = 0;
    //基本参数检查,不允许密文指针为空,密文长度不能为零值,且必须是4的整数倍.
    if (NULL == pstrEncoded || 0 == ulLenOfEncoded || 0 != (ulLenOfEncoded % 4))    return 0;
    //对密文进行解码,每4字节密文转换成3字节明文
    for (i = 0; i < ulLenOfEncoded; i++)
    {
        ucPiece = i % 4;
        //由密文字符转换成索引值[采用固定值的数组进行转换,可以提升转换速度,以空间换取时间的典型思路].
        sValue.bytes[ucPiece] = BASE64_INDEX[(unsigned char)pstrEncoded[i]];
        //填充字符转换成空中止
        if (64 == sValue.bytes[ucPiece])    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] = ((sValue.bytes[3] << 2) >> 2) | (sValue.bytes[2] << 6);
                //[密文]第3字节的3456位组成明文第2字节的低4位,[密文]第2字节的5678位组成明文第2字节的高4位.
                //cChar = ((sValue.bytes[2] << 2) >> 4) | (sValue.bytes[1] << 4);
                pstrText[ulLenOfText + 1] = ((sValue.bytes[2] << 2) >> 4) | (sValue.bytes[1] << 4);
                //[密文]第2字节的34位组成明文第1字节的低2位,[密文]第1字节的345678位组成明文第1字节的高6位.
                //cChar = (sValue.bytes[1] >> 4) | (sValue.bytes[0] << 2);
                pstrText[ulLenOfText + 0] = (sValue.bytes[1] >> 4) | (sValue.bytes[0] << 2);
            }
            ulLenOfText += 3;
            //sValue.value = 0;//重置(非必要操作,密文长度限定为4的整数倍);
        }
    }
    if (NULL != pstrText)    pstrText[ulLenOfText] = 0;//补充空中止
    return ulLenOfText;
}

//<<cpp-end>

使用方式示例:

    char strText[1024] = { 0 };
    Str_CopyA(strText, "Username:");
    BASE64_Encoded(strUsername, 64, strText, Str_LenA(strText));
    cout << "BASE64_Encoded:<" << strUsername << ">" << endl;
    Str_SetNullA(strText);
    BASE64_Decoded(strText, 64, strUsername, Str_LenA(strUsername));
    cout << "BASE64_Decoded:<" << strText << ">" << endl;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值