假装异步加载中...
11 Apr 2013

Base64加密解密算法的C/C++代码实现

今天再次用到了base64编解码,以前看过,现在又有点陌生了,上网查了下,然后用c++实现了下,在此记录下,以备将来查用。

介绍

百度百科维基百科说的很清楚,我就不罗嗦了

用途

Base64算法不是为了防止内容被人破解而使用的算法, 因为破解Base64太容易了, 就是简单的字符替换。 Base64还有个不好的地方,就是加密后, 长度会变成。 那我们为何还要使用Base64 呢?因为Base64可以把乱七八糟的二进制转化为字符串,这个特性在很多地方很有用。

实现(c++)

// Base64.h
#ifndef __BASE64_H__
#define __BASE64_H__

#include <string>
using std::string;

class CBase64
{
public:
    static bool Encode(const string& strIn,string& strOut);
    static bool Decode(const string& strIn,string& strOut,bool fCheckInputValid = false);
};

#endif
// Base64.cpp
#include "base64.h"

static const char encode_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char decode_map[256];
static void initBase64DecodeMap()
{
    memset(decode_map,-1,sizeof(decode_map));
    for (int i = 'A'; i <= 'Z'; ++i) decode_map[i] = 0 + (i - 'A');
    for (int i = 'a'; i <= 'z'; ++i) decode_map[i] = 26 + (i - 'a');
    for (int i = '0'; i <= '9'; ++i) decode_map[i] = 52 + (i - '0');
    decode_map[(unsigned char)'+'] = 62;
    decode_map[(unsigned char)'/'] = 63;
    decode_map[(unsigned char)'='] = 0;
}

bool CBase64::Encode(const string& strIn,string& strOut)
{
    size_t nInLen = strIn.length();
    size_t numOrig24BitValues = nInLen/3;
    bool havePadding = (nInLen != numOrig24BitValues*3);
    bool havePadding2 = (nInLen == numOrig24BitValues*3 + 1);
    size_t numResultBytes = 4*(numOrig24BitValues + havePadding);
    strOut.clear();
    for (size_t i = 0; i < numOrig24BitValues; ++i)
    {
        strOut.append(1,encode_map[(strIn[3*i] >> 2) & 0x3F]);
        strOut.append(1,encode_map[((strIn[3*i] << 4) & 0x30) | ((strIn[3*i+1] >> 4) & 0x0F)]);
        strOut.append(1,encode_map[((strIn[3*i+1] << 2) & 0x3C) | ((strIn[3*i+2] >> 6) & 0x03)]);
        strOut.append(1,encode_map[strIn[3*i+2] & 0x3F]);

    }

    if (havePadding)
    {
        size_t i = numOrig24BitValues;
        strOut.append(1,encode_map[(strIn[3*i] >> 2) & 0x3F]);
        if (havePadding2)
        {
            strOut.append(1,encode_map[((strIn[3*i] << 4) & 0x30) | ((strIn[3*i+1] >> 4) & 0x0F)]);
            strOut.append(1,'=');
        }
        else
        {
            strOut.append(1,encode_map[((strIn[3*i] << 4) & 0x30) | ((strIn[3*i+1] >> 4) & 0x0F)]);
            strOut.append(1,encode_map[((strIn[3*i+1] << 2) & 0x3C) | ((strIn[3*i+2] >> 6) & 0x03)]);
        }
        strOut.append(1,'=');
    }

    return true;
}

bool CBase64::Decode(const string& strIn,string& strOut,bool fCheckInputValid/* = false*/)
{
    size_t nInlen = strIn.length();
    if (nInlen < 4 || (nInlen % 4) != 0)
    {
        return false;
    }

    static bool bInit = false;
    if (!bInit)
    {
        initBase64DecodeMap();
        bInit = true;
    }

    if (fCheckInputValid)
    {
        for (size_t i = 0; i < nInlen; ++i)
        {
            if (decode_map[(unsigned char)strIn[i]] == -1)
            {
                return false;
            }
        }
    }
    size_t nOutLen = (nInlen * 3) / 4;
    string strTmpOut;
    strTmpOut.resize(nOutLen);
    size_t nLoopLen = nOutLen / 3;
    for (size_t i = 0; i < nLoopLen;++i)
    {
        strTmpOut[i*3] = ((decode_map[strIn[i*4]] << 2) & 0xFC) | ((decode_map[strIn[i*4+1]] >> 4) & 0x03);
        strTmpOut[i*3+1] = ((decode_map[strIn[i*4+1]] << 4) & 0xF0) | ((decode_map[strIn[i*4+2]] >> 2) & 0x0F);
        strTmpOut[i*3+2] = ((decode_map[strIn[i*4+2]] << 6) & 0xC0) | (decode_map[strIn[i*4+3]] & 0x3F);
    }

    if (strIn[nInlen - 1] == '=')
    {
        nOutLen--;
        if (strIn[nInlen - 2] == '=')
        {
            nOutLen--;
        }
    }
    const char* pData = strTmpOut.data();
    strOut.clear();
    strOut.append(pData,pData + nOutLen);
    return true;
}

获取

获取文件及更新:Github

PS: 在电子邮件中,根据RFC 822规定,每76个字符,还需要加上一个回车换行。这个是MIME中的规定,base64只是一种编码格式,并不是所有的应用都需要遵守这个原则。

comments powered by Disqus