#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','+','/','=' }; std::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]; } } 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(); 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; } } 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) { // 先将 plaintext 转为 utf8 std::string plain = unicode2Ansii(plaintext.c_str(), CP_UTF8); // 得到的 ss 为 ansii 编码,将其转为unicode 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) { // 先将 ciphertext 转为 ansii std::string cipher = unicode2Ansii(ciphertext.c_str(), CP_ACP); std::string plain = Decode(cipher); // 得到 plain 为utf8编码,将 plain 转为 unicode return ansii2Unicode(plain.c_str(), CP_UTF8); } ULONGLONG Base64::DecodeW2F(const std::wstring & ciphertext, CFile * pFile) { // cipher 转为 ansii 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; }