Do you have any sensitive data (e.g username, password, etc) which you think you want to encrypt it so that nobody can read it easily? In this article, i will show you how the task can be acheived easily by using Microsoft cryptography API. The following diagram shows the steps involved in this cryptography demo project.

Encryption and decryption flow diagram

Step 1: Acquire the Cryptographic Service Providers (CSP) based on our key container. In case it’s not available, we will create one in the system. Step 2: Create the hash object based on the algorithm applied to this demo project. We will hash the password used for encryption or decryption and add it to the hash object. Step 3: Generate a session key from hash object for encryption or decryption. Step 4: Start to encrypt or decrypt our data. More information about Microsoft cryptography API can be found in MDSN. Okay, enough for the story, let’s start the coding part now. 🙂 We start by include some of the necessary header files and 3 define statements
1
2
3
4
5
6
7
#include
#include  // this header is necessary for wincrypt.h
#include

#define ENCRYPT_ALGORITHM CALG_RC4  // we are using RC4 algorithm
#define KEYLENGTH  0x00800000
#define ENCRYPT_BLOCK_SIZE 8
The GetCryptContainer function will acquire and return the cryptographic service provider based on the key container. In case it failed to acquire CSP, it will create a new one based on the provided key container.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
HCRYPTPROV GetCryptContainer(LPCSTR keyContainer)
{
HCRYPTPROV hCryptProv = NULL;

if(CryptAcquireContext(
&hCryptProv,
keyContainer,
NULL,
PROV_RSA_FULL,
0))
{
printf("A cryptographic provider has been acquired.\n");
}
else
{
if (GetLastError() == NTE_BAD_KEYSET)
{
if(CryptAcquireContext(
&hCryptProv,
keyContainer,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("A new key container has been created.\n");
}
else
{
printf("Could not create a new key container.\n");
}
}
else
{
printf("A cryptographic service handle could not be acquired.\n");
}
}

return hCryptProv;
}
The CreateHashObjfunction will create and return hash object. It then will hash the password we use to encrypt or decrypt the data and add it the the hash object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
HCRYPTHASH CreateHashObj(HCRYPTPROV hCryptProv, const char * szPassword)
{
HCRYPTHASH hHash = NULL;

if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
printf("A hash object has been created. \n");

//  hash the password
if(CryptHashData(
hHash,
(BYTE *)szPassword,
strlen(szPassword),
0))
{
printf("The password has been added to the hash. \n");
}
else
{
// reset hash object to NULL
CryptDestroyHash(hHash);
hHash = NULL;
}
}
else
{
printf("Failed to create hash object.\n");
}

return hHash;
}
The GetDeriveKey functoin will generates cryptographic session keys derived from hash value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HCRYPTKEY GetDeriveKey(HCRYPTPROV hCryptProv, HCRYPTHASH hHash)
{
HCRYPTKEY hKey = NULL;

if(CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
printf("An encryption key is derived from the password hash. \n");
}
else
{
//MyHandleError("Error during CryptDeriveKey!\n");
}
return hKey;
}
This is the main entry of the demo project.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
int _tmain(int argc, char* argv[])
{
HCRYPTPROV hCryptProv = NULL;       // handle for a cryptographic
// provider context.
HCRYPTHASH hHash    = NULL;       // handle for hash object

LPCSTR keyContainer   = "MyKeyContainer"; // name of the key container
// to be used.
char szPassword[10]   = "12345";      // password for encryption and
// decryption
HCRYPTKEY hKey;               // handle for session key
PBYTE pbBuffer;               // hold the data being encrypt
// or decrypt
DWORD dwCount;                // data length

// make sure that we have enough argument to do the demo.
// otherwise exit the program
if(argc < 2)
{
printf("Usage: CryptoConsole.exe [data]");
exit(1);
}

// get CSP
hCryptProv = GetCryptContainer(keyContainer);

if(!hCryptProv)
exit(1); // exit if failed to get CSP

// get the hash object
hHash = CreateHashObj(hCryptProv, szPassword);

if(!hHash)
exit(1); // exit if failed to get hash object

// get the session key
hKey = GetDeriveKey(hCryptProv, hHash);

if(!hKey)
exit(1); // exit if failed to get session key

// determine input data length
int len = strlen(argv[1]);

// Determine the block size. If a block cipher is used,
// it must have room for an extra block.
DWORD dwBufferLen = len + ENCRYPT_BLOCK_SIZE - (len % ENCRYPT_BLOCK_SIZE);

// Allocate memory
if(pbBuffer = (BYTE *)malloc(dwBufferLen))
{
printf("Memory has been allocated for the buffer. \n");
}
else
{
printf("Failed to allocate memory for the buffer. \n");
exit(1);
}

// copy the data value to buffer
memcpy(pbBuffer, argv[1], dwBufferLen);
printf("++++++++++++++++++++++++++++++++\n");
printf("Before encryption: %s\n", argv[1]);
dwCount = strlen(argv[1]);

// encrypt data
if(!CryptEncrypt(
hKey,
0,
TRUE,
0,
pbBuffer,
&dwCount,
dwBufferLen))
{
printf("Error during CryptEncrypt. \n");
}
else
{
printf("After encryption: %s\n", pbBuffer);

unsigned char *pDecrypt = pbBuffer;
DWORD delen = _mbslen(pbBuffer);

// decrypt data
if(CryptDecrypt(
hKey,
0,
TRUE,
0,
pbBuffer,
&delen))
{
printf("After decryption: %s\n", pbBuffer);
printf("++++++++++++++++++++++++++++++++\n");
}
}

// Remove all references
if(pbBuffer)
free(pbBuffer);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hCryptProv)
CryptReleaseContext(hCryptProv,0);

return 0;
}
output: C++ encryption decryption output Download sample source code: CryptoConsole