#pragma once
#include "stdafx.h"
#include <Wincrypt.h>
class CCrypt
{
public:
CCrypt(void);
virtual ~CCrypt(void) {
if ( m_hKey ) CryptDestroyKey( m_hKey );
if ( m_hHash ) CryptDestroyHash( m_hHash );
if ( m_hProv ) CryptReleaseContext( m_hProv, 0);
}
BOOL SetKey( LPCSTR szKey= 0, LPCSTR pszSalt= 0 );
BOOL EncryptDecrypt( BYTE* pData, DWORD* dwDataLen, LPCSTR pKey, BOOL fEncrypt );
CString EncryptStrToHex( LPCSTR szText, LPCSTR pKey= 0, LPCSTR pszSalt= 0 );
CString DecryptStrFromHex( LPCSTR szHex, LPCSTR pKey= 0, LPCSTR pszSalt= 0 );
CString EncodeToHex( BYTE* p, int nLen );
int DecodeFromHex( LPCSTR pSrc, BYTE* pDest, int nBufLen );
private:
HCRYPTPROV m_hProv;
HCRYPTHASH m_hHash;
HCRYPTKEY m_hKey;
BOOL m_fOK;
DWORD m_nLastErr;
CString m_sErrMsg;
char* m_pszDefaultKeyRaw;
};
Crypt.cpp -- Code of the Encryption Object
#include "utCrypt.h"
CCrypt::CCrypt(void)
{
m_hProv= m_hHash= m_hKey= 0;
m_pszDefaultKeyRaw= "fdC)Y%yum3ww09";
}
BOOL CCrypt::SetKey( LPCSTR szKey, LPCSTR szSalt/*=0*/ )
{
m_fOK= TRUE;
if ( 0 == m_hProv ) {
m_fOK= CryptAcquireContext( &m_hProv, NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT
);
}
if ( m_fOK && (0 != m_hHash) ) {
m_fOK= CryptDestroyHash( m_hHash );
m_hHash= 0;
}
if ( m_fOK && (0 == m_hHash) ) {
m_fOK= CryptCreateHash( m_hProv, CALG_MD5, 0, 0, &m_hHash );
}
if ( m_fOK ) {
if ( 0 == szKey ) { // request to use default rawKey
char szTmp[100];
strcpy_s( szTmp, sizeof(szTmp), m_pszDefaultKeyRaw );
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
}
m_fOK= CryptHashData( m_hHash, (BYTE*)szKey, strlen(szKey), 0);
}
if ( m_fOK ) {
m_fOK= CryptDeriveKey( m_hProv, CALG_RC4, m_hHash, CRYPT_EXPORTABLE, &m_hKey);
}
if ( !m_fOK ) {
m_nLastErr= GetLastError();
m_sErrMsg= "Error creating encryption key";
}
return( m_fOK );
}
//--- workhorse function: Encrypt or decrypt "in place"
BOOL CCrypt::EncryptDecrypt( BYTE* pData, DWORD* dwDataLen, LPCSTR pKey, BOOL fEncrypt )
{
m_fOK= TRUE;
SetKey( (LPCSTR)pKey );
if ( fEncrypt ) {
m_fOK= CryptEncrypt( m_hKey, 0, TRUE, 0, pData, dwDataLen, *dwDataLen );
}
else {
m_fOK= CryptDecrypt( m_hKey, 0, TRUE, 0, pData, dwDataLen );
}
return( m_fOK );
}
CString CCrypt::EncryptStrToHex( LPCSTR szText, LPCSTR pszKey/*= 0*/, LPCSTR pszSalt/*= 0*/ )
{
m_fOK= TRUE;
CString sRet= "";
DWORD nDataLen= strlen( szText );
if ( pszSalt || pszKey || (0 == m_hKey) ) {
m_fOK= SetKey( (LPCSTR)pszKey, pszSalt );
}
if ( m_fOK ) {
char* pTmp= new char[nDataLen+1] ;
strncpy_s( pTmp, nDataLen+1, szText, nDataLen+1 );
m_fOK= CryptEncrypt( m_hKey, 0, TRUE, 0, (BYTE*)pTmp, &nDataLen, nDataLen );
if (m_fOK ) {
sRet= EncodeToHex( (BYTE*)pTmp, nDataLen );
}
delete pTmp;
}
return( sRet );
}
CString CCrypt::DecryptStrFromHex( LPCSTR szHex, LPCSTR pszKey/*=0*/, LPCSTR pszSalt/*= 0*/ )
{
m_fOK= TRUE;
CString sRet= "";
DWORD nDataLen= strlen( szHex );
if ( pszSalt || pszKey || (0 == m_hKey) ) {
m_fOK= SetKey( (LPCSTR)pszKey, pszSalt );
}
if ( m_fOK ) {
DWORD nDecryptLen= nDataLen/2;
char* pTmp= new char[ nDecryptLen+1 ];
DecodeFromHex( szHex, (BYTE*)pTmp, nDecryptLen );
m_fOK= CryptDecrypt( m_hKey, 0, TRUE, 0, (BYTE*)pTmp, &nDecryptLen );
if ( m_fOK ) {
sRet= pTmp;
}
delete pTmp;
}
return( sRet );
}
//--------------------------------------------------------
// inefficient but requires no explanation :-)
CString CCrypt::EncodeToHex( BYTE* p, int nLen )
{
CString sRet, sTmp;
for( int j=0; j< nLen; j++ ) {
sTmp.Format( "%02x", p[j] );
sRet+= sTmp;
}
return (sRet );
}
//---------------------------------------------------------
// returns length of decoded hex buffer
int CCrypt::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 );
}
#include "Crypt.h"
...
void CEncryptTestDlg::OnBnClickedButton1()
{
CCrypt crypt;
char szSrc[]="Secret Password";
//------------ use default rawKey
CString sEncrypted= crypt.EncryptStrToHex( szSrc );
CString sDecrypted= crypt.DecryptStrFromHex( sEncrypted );
MessageBox( sEncrypted,sDecrypted );
//------------ test use of wrong salt value
sEncrypted= crypt.EncryptStrToHex( szSrc, 0,"mySalt" );
sDecrypted= crypt.DecryptStrFromHex( sEncrypted,0,"yourSalt" ); // oops!
}
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (4)
Commented:
This code is not working for me...
1. I create new class "Crypt.h"
2.then "Crypt.cpp"
then during compilation VC++ asked me to add '#include "StdAfx.h"' in "Crypt.cpp" after that following list of errors appeared...
1>------ Build started: Project: EditPath, Configuration: Debug Win32 ------
1>Build started 3/1/2012 8:22:24 PM.
1>InitializeBuildStatus:
1> Touching "Debug\EditPath.unsuccessf
1>ClCompile:
1> All outputs are up-to-date.
1> Crypt.cpp
1>d:\ibs\editpath\editpath
1> Add directive to 'StdAfx.h' or rebuild precompiled header
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1> with
1> [
1> BaseType=wchar_t,
1> StringTraits=StrTraitMFC_D
1> ]
1> Constructor for class 'ATL::CStringT<BaseType,St
1> with
1> [
1> BaseType=wchar_t,
1> StringTraits=StrTraitMFC_D
1> ]
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1> with
1> [
1> BaseType=wchar_t,
1> StringTraits=StrTraitMFC_D
1> ]
1> Constructor for class 'ATL::CStringT<BaseType,St
1> with
1> [
1> BaseType=wchar_t,
1> StringTraits=StrTraitMFC_D
1> ]
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1>d:\ibs\editpath\editpath
1> with
1> [
1> BaseType=wchar_t,
1> StringTraits=StrTraitMFC_D
1> ]
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\ibs\editpath\editpath
1>
1>Build FAILED.
Author
Commented:Commented:
Commented:
Error 2 error LNK2019: unresolved external symbol "public: class std::basic_string<char,str
any clue to why this is being thrown? I am trying to add this to a DLL project I have. Is it possible to include in a TLL console app? or do I need to Create a dialog-based MFC App? I would prefer to just create the .cpp and .h files.