Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Registry Value Encryption and Decryption

0.00/5 (No votes)
25 Feb 2004 1  
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