Listing 2: Encryption support functions
#include "stdafx.h" #include <windows.h> #include <wincrypt.h> #include <malloc.h> #include <iostream.h> // Compute cyclic redundancy checksum - from Binstock & Rex unsigned short BinstockRexCRC(unsigned short crc, short data) { int i = 0; data <<= 8; for(i=8; i>0; i--) { if((data ^ crc) &0x8000) crc = (crc << 1) ^ 0x1021; else crc <<= 1; data <<= 1; } return(crc); } unsigned short ComputeCRC(long data) { unsigned short crc = 0; char *d = (char*)&data; for(int i=0; i<sizeof(long); i++) crc = BinstockRexCRC(crc, d[i]); return crc; } // Encrypt data with key bool Encrypt(const char *data,const char *key,char *ret,long size) { HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; HCRYPTKEY hKey = 0; BYTE *pbData = NULL; DWORD dwDataLen; if (!data || !key || !ret) return false; // Initialize CryptoAPI CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); CryptHashData(hHash, (BYTE*)key, strlen(key), 0); CryptDeriveKey(hProv, CALG_RC2, hHash, 0, &hKey); // How big a buffer do I need? dwDataLen = strlen(data)+1; CryptEncrypt(hKey,NULL,TRUE,0,NULL,&dwDataLen,0); // If the size is greater than half our buffer length, // we don't have enough room if (dwDataLen > (unsigned long) size/2) { if(pbData !=NULL) free(pbData); if(hHash) CryptDestroyHash(hHash); if(hKey) CryptDestroyKey(hKey); if(hProv) CryptReleaseContext(hProv,0); return false; } pbData = (BYTE*)malloc(dwDataLen); strcpy ((char*)pbData,data); DWORD inputBufferSize = dwDataLen; dwDataLen = strlen(data)+1; // Encrypt the data CryptEncrypt(hKey,NULL,TRUE,0,pbData,&dwDataLen, inputBufferSize); // Copy the encrypted data to a hex string char szBuf[3]; ret[0] = 0; for (int j=0; j< (int)dwDataLen; j++) { sprintf (szBuf,"%02X",pbData[j]); strcat(ret,szBuf); } if(pbData !=NULL) free(pbData); if(hHash) CryptDestroyHash(hHash); if(hKey) CryptDestroyKey(hKey); if(hProv) CryptReleaseContext(hProv,0); return true; } // Decrypt data with key bool Decrypt(const char *data,const char *key,char *ret,long size) { HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; HCRYPTKEY hKey = 0; BYTE *pbData = NULL; DWORD dwDataLen; if (!data || !key ||!ret || strlen(data)%2) return false; // Convert the string from hex to bin pbData = (BYTE*)malloc(strlen(data)/2+10); char szBuf[3]; for (int j=0; j<(int)strlen(data); j+=2) { szBuf[0] = data[j]; szBuf[1] = data[j+1]; szBuf[2] = 0; sscanf (szBuf,"%02X",pbData+j/2); } // Initialize the CryptoAPI CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); CryptHashData(hHash, (BYTE*)key, strlen(key), 0); CryptDeriveKey(hProv, CALG_RC2, hHash, 0, &hKey); dwDataLen = strlen(data)/2; // Decrypt the data CryptDecrypt(hKey,0,TRUE,0,pbData,&dwDataLen); // Is the return buffer big enough? if (dwDataLen > (unsigned long)size/2) { if(pbData !=NULL) free(pbData); if(hHash) CryptDestroyHash(hHash); if(hKey) CryptDestroyKey(hKey); if(hProv) CryptReleaseContext(hProv,0); return false; } strcpy(ret,(const char*)pbData); if(pbData !=NULL) free(pbData); if(hHash) CryptDestroyHash(hHash); if(hKey) CryptDestroyKey(hKey); if(hProv) CryptReleaseContext(hProv,0); return true; }