//--------------------------------------------------------------------------- #include "pch.h" #include "TWinCryptF.h" //--------------------------------------------------------------------------- #pragma package(smart_init) TWinCrypt::TWinCrypt() { FProv = FHash = FKey = 0; //FDefaultKeyRaw = "fdC)Y%yum3ww09"; FDefaultKeyRaw = (char*)"HfdC)A%yum3Nw09"; } //--------------------------------------------------------------------------- TWinCrypt::~TWinCrypt() { if (FKey) CryptDestroyKey(FKey); if (FHash) CryptDestroyHash(FHash); if (FProv) CryptReleaseContext(FProv, 0); FProv = FHash = FKey = 0; } //--------------------------------------------------------------------------- bool TWinCrypt::SetKey(LPCSTR szKey, LPCSTR szSalt/*=NULL*/) { FOk = true; if (!FProv) { FOk = CryptAcquireContext(&FProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ); } if (FOk && (0 != FHash)) { FOk = CryptDestroyHash(FHash); FHash = NULL; } if (FOk && (!FHash)) { FOk = CryptCreateHash(FProv, CALG_MD5, 0, 0, &FHash); } if (FOk) { if (!szKey) { // request to use default rawKey char szTmp[100]; strcpy_s( szTmp, sizeof(szTmp), FDefaultKeyRaw); if (szSalt) { strncat_s(szTmp, sizeof(szTmp), szSalt, 5); // use part of salt } // minor security tweak -- scramble the key+salt int nLen= strlen(szTmp)-1; for (int j = 0; j < nLen; j++) { char c = szTmp[nLen-j]; szTmp[nLen-j] = (char)(szTmp[j]+5); szTmp[j]= c; } szKey = &szTmp[4]; // discard the first part, for fun } FOk = CryptHashData(FHash, (BYTE*)szKey, strlen(szKey), 0); } if (FOk) { FOk = CryptDeriveKey(FProv, CALG_RC4, FHash, CRYPT_EXPORTABLE, &FKey); } if (!FOk) { FLastErr= GetLastError(); FErrMsg= "Error creating encryption key"; } return FOk; } //--------------------------------------------------------------------------- bool TWinCrypt::EncryptDecrypt(BYTE* pData, DWORD* dwDataLen, LPCSTR pKey, bool fEncrypt) { FOk = true; SetKey((LPCSTR)pKey); if (fEncrypt) { FOk = CryptEncrypt(FKey, 0, true, 0, pData, dwDataLen, *dwDataLen); } else { FOk = CryptDecrypt(FKey, 0, true, 0, pData, dwDataLen); } return FOk; } //--------------------------------------------------------------------------- std::string TWinCrypt::EncryptStrToHex(LPCSTR szText, LPCSTR pszKey/* = 0*/, LPCSTR pszSalt/* = 0*/) { FOk = true; std::string sRet= ""; DWORD nDataLen = strlen(szText); if (pszSalt || pszKey || (NULL == FKey)) { FOk = SetKey((LPCSTR)pszKey, pszSalt); } if (FOk) { char* pTmp = new char[nDataLen+1] ; strncpy_s(pTmp, nDataLen+1, szText, nDataLen+1); FOk = CryptEncrypt(FKey, 0, TRUE, 0, (BYTE*)pTmp, &nDataLen, nDataLen); if (FOk ) { sRet = EncodeToHex( (BYTE*)pTmp, nDataLen ); } delete pTmp; } return sRet; } //--------------------------------------------------------------------------- // inefficient but requires no explanation :-) std::string TWinCrypt::EncodeToHex(BYTE* p, int nLen) { std::string sRet; sRet = ""; for(int j = 0; j < nLen; j++) { char hexChars[3]; snprintf(hexChars, sizeof(hexChars), "%02X", p[j]); sRet += hexChars; } return sRet; } //--------------------------------------------------------------------------- std::string TWinCrypt::DecryptStrFromHex(LPCSTR szHex, LPCSTR pszKey/* = 0*/, LPCSTR pszSalt/* = 0*/) { FOk = TRUE; std::string sRet= ""; DWORD nDataLen= strlen(szHex); if (pszSalt || pszKey || (0 == FKey)) { FOk = SetKey((LPCSTR)pszKey, pszSalt); } if (FOk) { DWORD nDecryptLen = nDataLen/2; char* pTmp = new char[nDecryptLen+1]; DecodeFromHex(szHex, (BYTE*)pTmp, nDecryptLen); FOk = CryptDecrypt(FKey, 0, true, 0, (BYTE*)pTmp, &nDecryptLen ); if (FOk) { sRet= pTmp; } delete pTmp; } return sRet; } //--------------------------------------------------------------------------- // returns length of decoded hex buffer int TWinCrypt::DecodeFromHex(LPCSTR pSrc, BYTE* pDest, int nBufLen) { int nRet = 0; int nLen = strlen(pSrc); *pDest = 0; BYTE cIn1, cIn2, nFinal; for( int j=0; j< nLen; j += 2 ) { cIn1= (BYTE)toupper(*pSrc++); cIn1 -= '0'; if ( cIn1>9 ) cIn1 -= 7; cIn2= (BYTE)toupper(*pSrc++); cIn2 -= '0'; if ( cIn2>9 ) cIn2 -= 7; nFinal= (BYTE)((cIn1 << 4) | cIn2); if (nFinal>255) nFinal=0; // in case trying to decode non-hex data *pDest++ = nFinal; *pDest = 0; if ( nRet >= nBufLen ) { break; } nRet++; } return nRet; } //---------------------------------------------------------------------------