2025-04-27 07:49:33 -04:00

259 lines
5.7 KiB
C++

// SimpleCrypt.cpp : Implementation of CSimpleCrypt
#include "stdafx.h"
#include "Crypto.h"
#include "SimpleCrypt.h"
/////////////////////////////////////////////////////////////////////////////
// CSimpleCrypt
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CSimpleCrypt::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] = {&IID_ISimpleCrypt,};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
return S_FALSE;
}
///////////////////////////////////////
//The method encrypt bstrData and put the hex respresentation
// of encrypted data in pVal
////////////////////////////////////////
STDMETHODIMP CSimpleCrypt::Encrypt(BSTR bstrData, BSTR bstrKey, BSTR *pVal)
{
USES_CONVERSION;
BYTE* pbData;
DWORD dwDataLen;
TCHAR str[256];
DWORD dwErr;
// Initialize Key
if (InitKeys(bstrKey))
{
wsprintf(str, "InitKey failed!");
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
//Encrypt Data
dwDataLen = CComBSTR(bstrData).Length();
pbData = (BYTE*) malloc(dwDataLen+1);
lstrcpy((char*)pbData,W2A(bstrData));
if (!CryptEncrypt(m_hKey, 0, TRUE , 0, pbData, &dwDataLen, dwDataLen+1))
{
dwErr =GetLastError();
wsprintf(str, "CryptEncrypt failed!");
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
//Return to HEX representation
ToHex(pbData, dwDataLen, pVal);
return S_OK;
}
/////////////////////////////////////////////////////
// the method takes hex representation of encrypted data
// first convert it to binary representation and decrypt it,
// finally return the decrypted data
/////////////////////////////////////////////////////
STDMETHODIMP CSimpleCrypt::Decrypt(BSTR bstrEncrypted, BSTR bstrKey, BSTR *pVal)
{
USES_CONVERSION;
BYTE* pbData;
DWORD dwDataLen;
TCHAR str[256];
DWORD dwErr;
// initialize Key
if (InitKeys(bstrKey))
{
wsprintf(str, "InitKey failed!");
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
// convert bstrEncrypted to binary representation
CComBSTR bstrTmp(bstrEncrypted);
dwDataLen =bstrTmp.Length() /2;
pbData = (BYTE*) malloc(dwDataLen +1);
if (pbData == NULL)
{
return E_OUTOFMEMORY;
}
if (!ToBinary(bstrTmp, pbData, dwDataLen))
{
free(pbData);
wsprintf(str, "ToBinary() failed!");
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
// decrypt
if(!CryptDecrypt (m_hKey, 0, TRUE, 0, pbData, &dwDataLen))
{
free(pbData);
dwErr =GetLastError();
wsprintf(str, "CryptDecrypt failed!");
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
// convert the decrypted data to BSTR
*pVal = CComBSTR(dwDataLen+1, (LPCSTR)pbData).Copy();
return S_OK;
}
HRESULT CSimpleCrypt::FinalConstruct()
{
DWORD dwErr = 0;
TCHAR str[256];
// initialize member variables
m_dwKeySize =0;
m_hKey =NULL;
m_hKeyHash =NULL;
m_hProv =NULL;
if (!CryptAcquireContext(&m_hProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
dwErr = GetLastError();
if (dwErr == NTE_BAD_KEYSET)
{
dwErr=0;
if (!CryptAcquireContext(&m_hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
dwErr = GetLastError();
wsprintf(str, "CryptAcquireContext failed! Error.Number is %x", dwErr);
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
}
else
{
wsprintf(str, "Could not create Key Set! GetLastError %x", dwErr);
Error(str, IID_ISimpleCrypt);
return E_FAIL;
}
}
return dwErr;
}
HRESULT CSimpleCrypt::FinalRelease()
{
// clean up handles
if (m_hKeyHash != NULL) CryptDestroyHash(m_hKeyHash);
if (m_hKey != NULL) CryptDestroyKey(m_hKey);
if (m_hProv!=NULL) CryptReleaseContext(m_hProv, 0);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
DWORD CSimpleCrypt::InitKeys(BSTR bstrKey)
{
// clean up any old handles first
if (m_hKeyHash != NULL) CryptDestroyHash(m_hKeyHash);
if (m_hKey != NULL) CryptDestroyKey(m_hKey);
// generate a new key from key material provided in m_bstrKey
// this requires making a hash first, we'll use md5
if (!CryptCreateHash(m_hProv,CALG_MD5,0,0,&m_hKeyHash))
return GetLastError();
CComBSTR bstrTmp(bstrKey);
if (bstrTmp.Length() == 0)
return ERROR_INVALID_DATA;
if (!CryptHashData(m_hKeyHash,(LPBYTE)bstrTmp.m_str,bstrTmp.Length()*2,0))
return GetLastError();
if (!CryptDeriveKey(m_hProv,CALG_RC4,m_hKeyHash,0,&m_hKey))
return GetLastError();
return ERROR_SUCCESS;
}
void CSimpleCrypt::ToHex(BYTE* pbData, DWORD dwDataLen, BSTR* pHexRep)
{
DWORD i;
CComBSTR bstrHex;
char strTmp[16];
for (i =0; i < dwDataLen; i++)
{
sprintf(strTmp,"%02x", pbData[i]);
bstrHex.Append(strTmp);
}
*pHexRep = bstrHex.Copy();
return ;
}
BOOL CSimpleCrypt::ToBinary(CComBSTR bstrHexRep, BYTE* pbData, DWORD dwDataLen)
{
DWORD i, j;
BYTE hi, lo;
if (bstrHexRep.Length() > dwDataLen*2 )
return FALSE;
for (i=0, j=0; i < bstrHexRep.Length(); j++, i=i+2)
{
hi=(BYTE)bstrHexRep[i];
if(!ToBinary(hi))
return FALSE;
lo=(BYTE)bstrHexRep[i+1];
if(!ToBinary(lo))
return FALSE;
pbData[j] = (hi<<4) + lo;
}
return TRUE;
}
/////////////////////////////
BOOL CSimpleCrypt::ToBinary(BYTE& hexVal)
{
if (hexVal >='0' && hexVal <='9')
hexVal=hexVal-'0';
else if (hexVal >='a' && hexVal <='f')
hexVal=hexVal-'a'+10;
else if (hexVal >='A' && hexVal <='F')
hexVal=hexVal-'A'+10;
else
return FALSE;
return TRUE;
}