Click here to Skip to main content
15,892,059 members
Articles / Desktop Programming / MFC
Article

Registry Value Encryption and Decryption

Rate me:
Please Sign up or sign in to vote.
2.67/5 (9 votes)
25 Feb 20044 min read 126.5K   3.6K   42   18
Simple classes to perform crypt and registry operations

Introduction

This article shows how to store encrypted values into a registry entry and later retrieve them. The sample uses two classes CEncrypt (provides a wrapper for the encryption APIs) and CRegister(provides a wrapper for the registry operations). The registry key value encryption is useful when you want to store some sensitive data like database server username and password into the registry.The demo shows how to use these classes to write encrypted values into the registry ,as well as later retrieve these values and decrypt them to their original form.

Encryption

The encryption operations are declared in <wincrypt.h>

If you get problems including wincrypt.h,try the following:

#define _WIN32_WINNT 0x0400
#include "wincrypt.h"

If you don’t define _WIN32_WINNT then the content of wincrypt.h won’t get included

Actually, it can be any value greater than 0x0400. A peep into wincrypt.h will probably help.

CryptGenKey generates keys randomly so its of no use in our case,since the encryption and decryption should be performed by the same key.We need to generate a key which is derived from a base data e.g. a string of our choice.We should use CryptDeriveKey for this purpose.But there's some initialisation required before calling this particular function which can be dome in the done in the constructor for CEncrypt class.

The constructor code calls the following functions in the given order:

CryptAcquireContext(&cspContext,NULL,NULL,PROV_RSA_FULL ,0);

acquires an handle to the Cryptographic Service Provider (CSP )with the characteristics specified as the 4th parameter.The 3rd parameter is the name of service provider.If it is NULL then a handle to the default provider (“Microsoft Base Cryptographic Provider” ) is provided.

CryptCreateHash(cspContext,CALG_MD5,0,0,&hashData);

The above function creates a hash object. The valid values for the 2nd parameter depends on the CSP and the characteristics specified while acquiring the context.If the value of the parameter is not compatible with CSP characteristics it will give strange results via execution.

CryptHashData(hashData,(const unsigned 
char*)encryptKey.GetBuffer(256),encryptKey.GetLength(),0);

produces a hash data based on the string passed to the constructor and the hash object created in the previous step.

CryptDeriveKey(cspContext,CALG_RC2,hashData,0,&keyEncryption);

This function generates the key based on the hashed data available. Again the 2nd parameter value of "CALG_RC2" is dependent on the characteristics of the CSP.

All the crypt APIs discussed above return 1 on success and 0 on error.Besides,the above code guarantees that the key generated from same string will give equivalent keys. Now let us look into the functions Encrypt() and DeCrypt()

int     CEncrypt::Encrypt(char *msg,long orginalSize);

accepts the string to be encrypted and the orginal size of the buffer holding the string.It just calls CryptEncrypt API.The size of the encrypted text can be larger than the lenght of "msg" i.e., why we pass the original size of the buffer. If the buffer is not large enough to hold the encrypted text then a “NTE_NO_MEMORY” will be generated.After the encryption the “actualSize” param contains the actual size of the encrypted text.

The CEncrypt::DeCrypt just wraps up a call to CryptDecrypt API.

Registry Operations

The registry is organized into keys and their values.A key in turn can have subkeys. Before retrieving a value of the key or writing a new value into it,we need to open a key.This is what is being done in the CRegister class constructor.It accepts the name of the key which is supposed to be a descendent of the HKEY_CURRENT_USER.It obtains a handle to the key via a call to RegCreateKeyEx. The RegCreateKeyEx function creates the specified key. If the key already exists in the registry, the function opens it.The first param is the handle of an already open key or any of the predefined reserved HANDLE values like HKEY_CURRENT_USER.

Reading a Registry Value:

char *CRegister::getRegValue(char *key,DWORD *aSize);

accepts the keyName whose value is to be read.It returns a string with the key value and the size of the read data is returned in aSize. The code for this function looks as follows:

if(RegQueryValueEx(hKey, key, 0, &dwType,
 (PBYTE)NULL, &dwDataSize)==ERROR_SUCCESS && hKey!=NULL)
{
dest=(char *)malloc(sizeof(char)*256);
RegQueryValueEx(hKey, key, 0,&dwType,(PBYTE)(LPTSTR)dest,&dwDataSize);
}

RegQueryValueEx is used to retrieve the value from registry. The first call with the buffer set to NULL is for knowing the size of the key value,so that we can allocate adequate memory space for the registry value during the second call.

Setting a Registry Value:

void CRegister::setRegValue(char *key,char * newValue,long actualSize);

setRegValue simply sets the value of a key to a given data using the RegSetValueEx API.

Points to Note

dwType in RegQueryValueEx and RegSetValueEx which specifies type of value’s data is set to REG_BINARY, i.e., we read and writevalues in binary form.This is done to avoid unnecessary translation of special characters while reading and writing to registry. For example suppose after encryption we get the following string “99 63 AF 00 1F F5 5E 3C” where the values in quotes represent the ascii values of characters in hexadecimal format. Notice the NULL character represented by “00”.Now if you set the dwType as REG_SZ the string “99 63 AF 00” will only be written to registry. So information is lost and you cannot decrypt this incomplete string.For the same reason avoid using standard C-string functions on the value fetched from the registry.For example in the above case "strlen" will give length as 3 whereas the actual size is 8.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalperfect!! Pin
bljacobs5-Mar-10 15:32
bljacobs5-Mar-10 15:32 
QuestionHow to use it in windows 98? Pin
johnthecoder29-Dec-08 19:17
johnthecoder29-Dec-08 19:17 
GeneralMemory leaks Pin
krssagar18-Aug-04 23:33
krssagar18-Aug-04 23:33 
GeneralPlease, check for bugs Pin
__PPS__17-Jun-04 11:22
__PPS__17-Jun-04 11:22 
GeneralFailing to encrypt Pin
Dick Heth6-Apr-04 6:08
Dick Heth6-Apr-04 6:08 
GeneralRe: Failing to encrypt Pin
Dick Heth6-Apr-04 7:01
Dick Heth6-Apr-04 7:01 
GeneralRe: Failing to encrypt Pin
jithus6-Apr-04 18:17
jithus6-Apr-04 18:17 
GeneralRe: Failing to encrypt Pin
pflei14-Sep-04 14:58
pflei14-Sep-04 14:58 
GeneralRe: Failing to encrypt Pin
Hamid Reza Mohammadi1-Jul-05 21:43
Hamid Reza Mohammadi1-Jul-05 21:43 
GeneralRe: Failing to encrypt Pin
ywimmer7-Sep-11 21:31
ywimmer7-Sep-11 21:31 
GeneralRe: Failing to encrypt Pin
Mahadev HK19-Oct-13 23:26
Mahadev HK19-Oct-13 23:26 
Generalhelp me, I can't include &quot;wincrypt.h&quot; Pin
LoLem23-Mar-04 22:46
LoLem23-Mar-04 22:46 
GeneralRe: help me, I can't include &quot;wincrypt.h&quot; Pin
jithus23-Mar-04 23:03
jithus23-Mar-04 23:03 
GeneralRe: help me, I can't include &quot;wincrypt.h&quot; Pin
rq99bq30-Jul-04 3:50
rq99bq30-Jul-04 3:50 
GeneralGood Example, but needs a little more Pin
bumbobway2-Mar-04 20:05
bumbobway2-Mar-04 20:05 
This is a good basic example of how to use the CryptoAPI. There are a few additional steps you might want to take:

1.) I read the source code, and he's storing his private key in the source code. That's a no-no. It wouldn't take much to dig this out of a binary using a hex editor or attaching a debugger to the process, and we could read the value passed to the constructor. A good idea is to find a way to programmatically hide the private key value within the source code. Also, immediately after use, you should write random data over your buffers that store your un-encrypted data and your private key. This will prevent anyone from intercepting your data.

2.) When encrypting your value, you should pad the beginning and end of your value with junk. If you make all your encrypted values the same length, there is no way a hacker can figure out where the value starts and the junk ends. This will prevent anyone from running a decrypt algorithm to determine your hashed string.

jg
GeneralRe: Good Example, but needs a little more Pin
Jimmy M Joy2-Mar-04 22:59
Jimmy M Joy2-Mar-04 22:59 
GeneralRe: Good Example, but needs a little more Pin
John M. Drescher4-Mar-04 11:02
John M. Drescher4-Mar-04 11:02 
GeneralRe: Good Example, but needs a little more Pin
jithus8-Mar-04 3:22
jithus8-Mar-04 3:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.