2026-10-04 00:04:20 +08:00
|
|
|
|
#include "StdAfx.h"
|
2026-09-28 15:28:50 +08:00
|
|
|
|
#include "Base64.h"
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
|
#undef THIS_FILE
|
|
|
|
|
|
static char THIS_FILE[]=__FILE__;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
|
{
|
|
|
|
|
|
char code[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','+','/','=' };
|
|
|
|
|
|
|
|
|
|
|
|
std::string encode(const char *pBuff, const ULONGLONG &len)
|
|
|
|
|
|
{
|
2026-10-04 00:04:20 +08:00
|
|
|
|
int textSize = len; //明文长度
|
|
|
|
|
|
int resultSize = (textSize + 2) / 3 * 4; //密文长度
|
|
|
|
|
|
char* pText = new char[textSize + 1]; //多开辟一个内存空间用于存储'\0'
|
|
|
|
|
|
char* pResult = new char[resultSize + 1]; //多开辟一个内存空间用于存储'\0'
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
|
|
|
|
|
::memset(pText, 0, sizeof(char) * (textSize + 1));
|
|
|
|
|
|
::memset(pResult, 0, sizeof(char) * (resultSize + 1));
|
|
|
|
|
|
::memcpy(pText, pBuff, sizeof(char) * (textSize + 1));
|
|
|
|
|
|
|
|
|
|
|
|
pText[textSize] = '\0';
|
|
|
|
|
|
pResult[resultSize] = '\0';
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
int textIndex = 0;//pText的下标
|
|
|
|
|
|
int resultIndex;//pResult的下标
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
//加密明文,但不包括密文的最后四个字符,因为明文长度可能不是 3 的整数倍,密文会以‘=’结尾
|
2026-09-28 15:28:50 +08:00
|
|
|
|
for (resultIndex = 0; resultIndex < resultSize - 4; resultIndex += 4, textIndex += 3)
|
|
|
|
|
|
{
|
|
|
|
|
|
char a, b, c;
|
|
|
|
|
|
a = pText[textIndex];
|
|
|
|
|
|
b = pText[textIndex + 1];
|
|
|
|
|
|
c = pText[textIndex + 2];
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
int index;
|
|
|
|
|
|
switch (i)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:index = (a >> 2 & 0x3F); break;
|
|
|
|
|
|
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
|
|
|
|
|
|
case 2:index = (b << 2 & 0x3C) | (c >> 6 & 0x03); break;
|
|
|
|
|
|
case 3:index = (c & 0x3F); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
pResult[resultIndex + i] = code[index];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
//判断明文剩余几个字符,并加密
|
|
|
|
|
|
if (textIndex == textSize - 1)//余一个字符,密文末尾有两个‘=’
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
char a, b;
|
|
|
|
|
|
a = pText[textIndex];
|
|
|
|
|
|
b = 0;
|
|
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
int index;
|
|
|
|
|
|
switch (j)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:index = (a >> 2 & 0x3F); break;
|
|
|
|
|
|
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
|
|
|
|
|
|
case 2:index = 64; break;
|
|
|
|
|
|
case 3:index = 64; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
pResult[resultIndex + j] = code[index];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
else if ((textIndex + 1) == textSize - 1)//余两个字符,密文末尾有一个‘=’
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
char a, b, c;
|
|
|
|
|
|
a = pText[textIndex];
|
|
|
|
|
|
b = pText[textIndex + 1];
|
|
|
|
|
|
c = 0;
|
|
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
int index;
|
|
|
|
|
|
switch (j)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:index = (a >> 2 & 0x3F); break;
|
|
|
|
|
|
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
|
|
|
|
|
|
case 2:index = (b << 2 & 0x3C) | (c >> 6 & 0x03); break;
|
|
|
|
|
|
case 3:index = 64; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
pResult[resultIndex + j] = code[index];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
else//是三的整数倍,密文末尾没有‘=’
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
char a, b, c;
|
|
|
|
|
|
a = pText[textIndex];
|
|
|
|
|
|
b = pText[textIndex + 1];
|
|
|
|
|
|
c = pText[textIndex + 2];
|
|
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
int index;
|
|
|
|
|
|
switch (j)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:index = (a >> 2 & 0x3F); break;
|
|
|
|
|
|
case 1:index = (a << 4 & 0x30) | (b >> 4 & 0x0F); break;
|
|
|
|
|
|
case 2:index = (b << 2 & 0x3C) | (c >> 6 & 0x03); break;
|
|
|
|
|
|
case 3:index = (c & 0x3F); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
pResult[resultIndex + j] = code[index];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string strOut(pResult);
|
|
|
|
|
|
|
|
|
|
|
|
delete[] pText;
|
|
|
|
|
|
delete[] pResult;
|
|
|
|
|
|
pText = NULL;
|
|
|
|
|
|
pResult = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
return strOut;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONGLONG decode(const std::string &ciphertext, char *&pResult)
|
|
|
|
|
|
{
|
|
|
|
|
|
int textSize = ciphertext.size();
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
if (textSize % 4 != 0)//Base64密文的长度应该是4的倍数
|
2026-09-28 15:28:50 +08:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
int resultSize = textSize / 4 * 3;//明文的长度
|
2026-09-28 15:28:50 +08:00
|
|
|
|
char* pText = new char[textSize + 1];
|
|
|
|
|
|
pResult = new char[resultSize + 1];
|
|
|
|
|
|
|
|
|
|
|
|
ciphertext.copy(pText, textSize, 0);
|
|
|
|
|
|
pText[textSize] = '\0';
|
|
|
|
|
|
pResult[resultSize] = '\0';
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
int textIndex = 0;//pText的下标
|
|
|
|
|
|
int resultIndex;//pResult的下标
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
int index[4];//存储字符在code种的位置
|
|
|
|
|
|
//解密密文,但不解密最后四个字符,因为密文最后四位可能包括‘=’
|
2026-09-28 15:28:50 +08:00
|
|
|
|
for (resultIndex = 0; resultIndex < resultSize - 3; resultIndex += 3, textIndex += 4)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int m = 0; m < 4; m++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pText[textIndex + m] >= 'A' && pText[textIndex + m] <= 'Z')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = pText[textIndex + m] - 65;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] >= 'a' && pText[textIndex + m] <= 'z')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = pText[textIndex + m] - 71;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] >= '0' && pText[textIndex + m] <= '9')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = pText[textIndex + m] + 4;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] == '+')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = 62;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] == '/')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = 63;
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
else //如果密文包括其他字符则不是正确的Base64编码
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
delete[] pText;
|
|
|
|
|
|
delete[] pResult;
|
|
|
|
|
|
pText = pResult = NULL;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
|
|
|
|
|
|
pResult[resultIndex + 1] = (index[1] << 4 & 0xF0) | (index[2] >> 2 & 0x0F);
|
|
|
|
|
|
pResult[resultIndex + 2] = (index[2] << 6 & 0xC0) | index[3];
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
//处理密文的最后四位
|
2026-09-28 15:28:50 +08:00
|
|
|
|
for (int m = 0; m < 4; m++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pText[textIndex + m] >= 'A' && pText[textIndex + m] <= 'Z')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = pText[textIndex + m] - 65;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] >= 'a' && pText[textIndex + m] <= 'z')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = pText[textIndex + m] - 71;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] >= '0' && pText[textIndex + m] <= '9')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = pText[textIndex + m] + 4;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] == '+')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = 62;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] == '/')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = 63;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pText[textIndex + m] == '=')
|
|
|
|
|
|
{
|
|
|
|
|
|
index[m] = 64;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
delete[] pText;
|
|
|
|
|
|
delete[] pResult;
|
|
|
|
|
|
pText = pResult = NULL;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
if (index[2] == 64)//密文末尾有两个 =
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
|
|
|
|
|
|
pResult[resultIndex + 1] = '\0';
|
|
|
|
|
|
pResult[resultIndex + 2] = '\0';
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
else if (index[3] == 64)//密文末尾有一个 =
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
|
|
|
|
|
|
pResult[resultIndex + 1] = (index[1] << 4 & 0xF0) | (index[2] >> 2 & 0x0F);
|
|
|
|
|
|
pResult[resultIndex + 2] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2026-10-04 00:04:20 +08:00
|
|
|
|
else//密文末尾没有 =
|
2026-09-28 15:28:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
|
|
|
|
|
|
pResult[resultIndex + 1] = (index[1] << 4 & 0xF0) | (index[2] >> 2 & 0x0F);
|
|
|
|
|
|
pResult[resultIndex + 2] = (index[2] << 6 & 0xC0) | index[3];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
delete[] pText;
|
|
|
|
|
|
pText = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
return resultSize + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string Base64::Encode(const char * pBuffer, const ULONGLONG & length)
|
|
|
|
|
|
{
|
|
|
|
|
|
return encode(pBuffer, length);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONGLONG Base64::Decode(const std::string & ciphertext, char *& pBuffer)
|
|
|
|
|
|
{
|
|
|
|
|
|
return decode(ciphertext, pBuffer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string Base64::Encode(const std::string& plaintext)
|
|
|
|
|
|
{
|
|
|
|
|
|
int textSize=plaintext.size() * sizeof(char);
|
|
|
|
|
|
char* pText=new char[textSize];
|
|
|
|
|
|
::memcpy(pText, plaintext.data(), sizeof(char) * textSize);
|
|
|
|
|
|
|
|
|
|
|
|
std::string str = encode(pText, textSize);
|
|
|
|
|
|
|
|
|
|
|
|
delete[] pText;
|
|
|
|
|
|
pText = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string Base64::Decode(const std::string& ciphertext)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *pBuff(NULL);
|
|
|
|
|
|
ULONGLONG len = decode(ciphertext, pBuff);
|
|
|
|
|
|
|
|
|
|
|
|
if (!pBuff) return "";
|
|
|
|
|
|
|
|
|
|
|
|
std::string str(pBuff);
|
|
|
|
|
|
|
|
|
|
|
|
delete[] pBuff;
|
|
|
|
|
|
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string Base64::EncodeF2S(CFile * pFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
pFile->SeekToBegin();
|
|
|
|
|
|
|
|
|
|
|
|
ULONGLONG len = pFile->GetLength();
|
|
|
|
|
|
char *psz = new char[len];
|
|
|
|
|
|
::memset(psz, 0, sizeof(char) * len);
|
|
|
|
|
|
pFile->Read(psz, len);
|
|
|
|
|
|
|
|
|
|
|
|
std::string str = encode(psz, len);
|
|
|
|
|
|
|
|
|
|
|
|
delete[] psz;
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONGLONG Base64::DecodeS2F(const std::string& ciphertext, CFile * pFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *pBuff(NULL);
|
|
|
|
|
|
ULONGLONG len = decode(ciphertext, pBuff);
|
|
|
|
|
|
if (!len || !pBuff) return 0L;
|
|
|
|
|
|
|
|
|
|
|
|
pFile->SetLength(0L);
|
|
|
|
|
|
pFile->SeekToBegin();
|
|
|
|
|
|
pFile->Write(pBuff, len);
|
|
|
|
|
|
|
|
|
|
|
|
delete[] pBuff;
|
|
|
|
|
|
pBuff = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::wstring Base64::Encode(const std::wstring & plaintext)
|
|
|
|
|
|
{
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 先将 plaintext 转为 utf8
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string plain = unicode2Ansii(plaintext.c_str(), CP_UTF8);
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 得到的 ss 为 ansii 编码,将其转为unicode
|
2026-09-28 15:28:50 +08:00
|
|
|
|
return ansii2Unicode(plain.c_str(), CP_ACP);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::wstring Base64::EncodeF2W(CFile * pFile)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string cipher = EncodeF2S(pFile);
|
|
|
|
|
|
return ansii2Unicode(cipher.c_str(), CP_ACP);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::wstring Base64::Decode(const std::wstring & ciphertext)
|
|
|
|
|
|
{
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 先将 ciphertext 转为 ansii
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string cipher = unicode2Ansii(ciphertext.c_str(), CP_ACP);
|
|
|
|
|
|
|
|
|
|
|
|
std::string plain = Decode(cipher);
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 得到 plain 为utf8编码,将 plain 转为 unicode
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
|
|
|
|
|
return ansii2Unicode(plain.c_str(), CP_UTF8);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONGLONG Base64::DecodeW2F(const std::wstring & ciphertext, CFile * pFile)
|
|
|
|
|
|
{
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// cipher 转为 ansii
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string cipher = unicode2Ansii(ciphertext.c_str(), CP_ACP);
|
|
|
|
|
|
return DecodeS2F(cipher, pFile);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string Base64::unicode2Ansii(LPCTSTR psz, const DWORD & codePage)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!psz) return std::string("");
|
|
|
|
|
|
|
|
|
|
|
|
char *pBuffer;
|
|
|
|
|
|
int nLength;
|
|
|
|
|
|
int nLen;
|
|
|
|
|
|
|
|
|
|
|
|
nLen = (int)wcslen(psz);
|
|
|
|
|
|
nLength = ::WideCharToMultiByte(codePage, 0, psz, nLen, NULL, 0, 0, 0);
|
|
|
|
|
|
int rc = ::GetLastError();
|
|
|
|
|
|
pBuffer = new char[nLength + 1];
|
|
|
|
|
|
memset(pBuffer, 0, (nLength + 1) * sizeof(char));
|
|
|
|
|
|
::WideCharToMultiByte(codePage, 0, psz, nLen, pBuffer, nLength, 0, 0);
|
|
|
|
|
|
std::string str(pBuffer);
|
|
|
|
|
|
delete[] pBuffer;
|
|
|
|
|
|
return str;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::wstring Base64::ansii2Unicode(LPCSTR psz, const DWORD & codePage)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!psz) return std::wstring(L"");
|
|
|
|
|
|
|
|
|
|
|
|
int nLength, nLen;
|
|
|
|
|
|
wchar_t *pBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
nLen = (int)strlen(psz);
|
|
|
|
|
|
nLength = ::MultiByteToWideChar(codePage, 0, psz, nLen, NULL, 0);
|
|
|
|
|
|
pBuffer = new wchar_t[nLength + 1];
|
|
|
|
|
|
memset(pBuffer, 0, (nLength + 1) * sizeof(wchar_t));
|
|
|
|
|
|
::MultiByteToWideChar(codePage, 0, psz, nLen, (LPWSTR)pBuffer, nLength);
|
|
|
|
|
|
std::wstring wstr(pBuffer);
|
|
|
|
|
|
delete[] pBuffer;
|
|
|
|
|
|
return wstr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|