379 lines
9.1 KiB
C++
379 lines
9.1 KiB
C++
#include "StdAfx.h"
|
||
#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','+','/','=' };
|
||
|
||
string encode(const char *pBuff, const ULONGLONG &len)
|
||
{
|
||
int textSize = len; //明文长度
|
||
int resultSize = (textSize + 2) / 3 * 4; //密文长度
|
||
char* pText = new char[textSize + 1]; //多开辟一个内存空间用于存储'\0'
|
||
char* pResult = new char[resultSize + 1]; //多开辟一个内存空间用于存储'\0'
|
||
|
||
::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';
|
||
|
||
int textIndex = 0;//pText的下标
|
||
int resultIndex;//pResult的下标
|
||
|
||
//加密明文,但不包括密文的最后四个字符,因为明文长度可能不是 3 的整数倍,密文会以‘=’结尾
|
||
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];
|
||
}
|
||
}
|
||
|
||
//判断明文剩余几个字符,并加密
|
||
if (textIndex == textSize - 1)//余一个字符,密文末尾有两个‘=’
|
||
{
|
||
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];
|
||
}
|
||
|
||
}
|
||
else if ((textIndex + 1) == textSize - 1)//余两个字符,密文末尾有一个‘=’
|
||
{
|
||
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];
|
||
}
|
||
}
|
||
else//是三的整数倍,密文末尾没有‘=’
|
||
{
|
||
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];
|
||
}
|
||
}
|
||
|
||
string strOut(pResult);
|
||
|
||
delete[] pText;
|
||
delete[] pResult;
|
||
pText = NULL;
|
||
pResult = NULL;
|
||
|
||
return strOut;
|
||
}
|
||
|
||
ULONGLONG decode(const string &ciphertext, char *&pResult)
|
||
{
|
||
int textSize = ciphertext.size();
|
||
|
||
if (textSize % 4 != 0)//Base64密文的长度应该是4的倍数
|
||
return 0;
|
||
|
||
int resultSize = textSize / 4 * 3;//明文的长度
|
||
char* pText = new char[textSize + 1];
|
||
pResult = new char[resultSize + 1];
|
||
|
||
ciphertext.copy(pText, textSize, 0);
|
||
pText[textSize] = '\0';
|
||
pResult[resultSize] = '\0';
|
||
|
||
int textIndex = 0;//pText的下标
|
||
int resultIndex;//pResult的下标
|
||
|
||
int index[4];//存储字符在code种的位置
|
||
//解密密文,但不解密最后四个字符,因为密文最后四位可能包括‘=’
|
||
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;
|
||
}
|
||
else //如果密文包括其他字符则不是正确的Base64编码
|
||
{
|
||
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];
|
||
}
|
||
//处理密文的最后四位
|
||
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;
|
||
}
|
||
}
|
||
if (index[2] == 64)//密文末尾有两个 =
|
||
{
|
||
pResult[resultIndex] = (index[0] << 2 & 0XFC) | (index[1] >> 4 & 0x03);
|
||
pResult[resultIndex + 1] = '\0';
|
||
pResult[resultIndex + 2] = '\0';
|
||
}
|
||
else if (index[3] == 64)//密文末尾有一个 =
|
||
{
|
||
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';
|
||
|
||
}
|
||
else//密文末尾没有 =
|
||
{
|
||
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;
|
||
}
|
||
}
|
||
|
||
string Base64::Encode(const char * pBuffer, const ULONGLONG & length)
|
||
{
|
||
return encode(pBuffer, length);
|
||
}
|
||
|
||
ULONGLONG Base64::Decode(const 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);
|
||
|
||
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 "";
|
||
|
||
string str(pBuff);
|
||
|
||
delete[] pBuff;
|
||
|
||
return str;
|
||
}
|
||
|
||
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);
|
||
|
||
string str = encode(psz, len);
|
||
|
||
delete[] psz;
|
||
return str;
|
||
}
|
||
|
||
ULONGLONG Base64::DecodeS2F(const 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;
|
||
}
|
||
|
||
wstring Base64::Encode(const wstring & plaintext)
|
||
{
|
||
// 先将 plaintext 转为 utf8
|
||
string plain = unicode2Ansii(plaintext.c_str(), CP_UTF8);
|
||
// 得到的 ss 为 ansii 编码,将其转为unicode
|
||
return ansii2Unicode(plain.c_str(), CP_ACP);
|
||
}
|
||
|
||
wstring Base64::EncodeF2W(CFile * pFile)
|
||
{
|
||
string cipher = EncodeF2S(pFile);
|
||
return ansii2Unicode(cipher.c_str(), CP_ACP);
|
||
}
|
||
|
||
wstring Base64::Decode(const wstring & ciphertext)
|
||
{
|
||
// 先将 ciphertext 转为 ansii
|
||
string cipher = unicode2Ansii(ciphertext.c_str(), CP_ACP);
|
||
|
||
string plain = Decode(cipher);
|
||
// 得到 plain 为utf8编码,将 plain 转为 unicode
|
||
|
||
return ansii2Unicode(plain.c_str(), CP_UTF8);
|
||
}
|
||
|
||
ULONGLONG Base64::DecodeW2F(const wstring & ciphertext, CFile * pFile)
|
||
{
|
||
// cipher 转为 ansii
|
||
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;
|
||
}
|
||
|