Click here to Skip to main content
12,628,454 members (35,120 online)
Click here to Skip to main content
Add your own
alternative version

Stats

271.8K views
13.4K downloads
79 bookmarked
Posted

Encryption using the Win32 Crypto API

, 8 Sep 2005
Rate this:
Please Sign up or sign in to vote.
How to encrypt using the Win32 Crypto API.

Introduction

Using information technology today gets more and more sophisticated. The information that is being transferred and stored are often classified material of some kind and it is often necessary to prevent it from being read by third parties. The keyword for this particular problem is (both logical and physical) security. A part of the security aspect is encryption. Often people think that security is “just” something you plug in afterwards – it is definitely not!

A few rules of thumb when encryption is going to be included in the final product can be summarised into the following basics:

  1. Do not base the encryption on the algorithm itself.
  2. Make the algorithm public and the key private.

RSA Encryption

One of the most well known encryptions today is the RSA encryption. This form for encryption uses asymmetric keys. This means that you cannot evaluate the second key if you have the first one and vice versa.

The RSA encryption is a public-key crypto system, which uses two algorithms (E, D), one for encryption and one for decryption. You have a key pair containing: a secret key (sk) and a public key (pk).

m = D sk (E pk (m))
m = cd mod n AND c = me mod n <=>
m = (me mod n)d mod n

CBC Mode

The RSA encryption is typically using CBC mode (Cipher Block Chaining mode) when encrypting. This means the text that is being encrypted is divided into blocks. Each block is chained together, using the XOR operator, and then encrypted.

Sample screenshot

When using the CBC mode of operation it is required that all blocks have the same size. If the last block has a size less than the others then it will be necessary to use padding. The padding will then fill the block until it has the same size as the others. Formally the CBC mode operates in the following way, where we start with y0, which is a 64-bit initialisation vector:

y i = e k (y i-1 XOR x i), i >= 1

Doing the decryption, the entire operation is just reversed. This means that the cipher blocks are decrypted and then XORed. In this way we will end up with the clear text again.

x i = y i-1 XOR (d k (y i)) , i >= 1

Using the code

The Win32 Crypto API does provide some functionality, which can be used to perform an encryption. The advantage using the Crypto API is that you don’t need to use/find any third party cryptographic provider and figure out how it is installed and used. Simply use the one that sticks to the operating system. The disadvantage is clear – it is not simple to change to another operation system.

Sample screenshot

Before any functionality can be used it is necessary to create a context. This context is used several times when doing the encryption, so it is important that the handle is kept open until the encryption is done.

if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0))
{
    dwResult = GetLastError();
    if (dwResult == NTE_BAD_KEYSET)
    {
        if (!CryptAcquireContext(&hProv, 
            NULL, MS_DEF_PROV, PROV_RSA_FULL, 
            CRYPT_NEWKEYSET))
        {
            dwResult = GetLastError();
            MessageBox("Error [0x%x]: CryptAcquireContext() failed.", 
                       "Information", MB_OK);
            return;
        }
    }
    else {
        dwResult = GetLastError();
        return;
    }
}

When we get the context, we need to get a (session) key, which we are going to use when doing the encryption. The key can be created from scratch or it can be imported from a file. In the following code snip, the pbBlob is (if not NULL) a binary that contains the key, which is fetched from a file.

if (pbBlob) {
    if (!CryptImportKey(hProv, pbBlob, cbBlob, 0, 0, &hSessionKey))
    {
        dwResult = GetLastError();
        MessageBox("Error [0x%x]: CryptImportKey() failed.", 
                                      "Information", MB_OK);
        return;
    }
}
else { 
    if (!CryptImportKey(hProv, PrivateKeyWithExponentOfOne, 
        sizeof(PrivateKeyWithExponentOfOne), 0, 0, &hKey))
    {
        dwResult = GetLastError();
        MessageBox("Error CryptImportKey() failed.", 
                              "Information", MB_OK);
        return;
    }
    if (!CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hSessionKey))
    {
        dwResult = GetLastError();
        MessageBox("Error CryptGenKey() failed.", 
                           "Information", MB_OK);
        return;
    }
}

It is always a good idea to use the PKCS#7 standard, when storing the key. Please note that the project enclosed with this article does not use it.

After the key is imported or generated, it is now time to perform the encryption or decryption. The encryption and decryption depends on a session key, which is based on the key we just imported or generated previously.

void Encrypt()
{
    unsigned long length = m_clear.GetLength() +1;
    unsigned char * cipherBlock = (unsigned char*)malloc(length);
    memset(cipherBlock, 0, length);
    memcpy(cipherBlock, m_clear, length -1); 

    if (!CryptEncrypt(hSessionKey, 0, TRUE, 0, cipherBlock, &length, length))
    {
        dwResult = GetLastError();
        MessageBox("Error CryptEncrypt() failed.", "Information", MB_OK);
        return;
    }

    m_cipher = cipherBlock;
    m_clear = "";
    free(cipherBlock);
}

The decryption does not vary much from the encryption. Like with the encryption it is done with just one invocation and the cipher text is then decrypted.

void Decrypt()
{
    unsigned long length = m_cipher.GetLength() +1;
    unsigned char * cipherBlock = (unsigned char*)malloc(length);
    memset(cipherBlock, 0, length);
    memcpy(cipherBlock, m_cipher, length -1); 

    if (!CryptDecrypt(hSessionKey, 0, TRUE, 0, cipherBlock, &length))
    {
        dwResult = GetLastError();
        MessageBox("Error CryptDecrypt() failed.", 
                            "Information", MB_OK);
        return;
    }

    m_clear = cipherBlock;
    m_cipher = "";

    free(cipherBlock);
}

Points of interest

The clear text / data is typically a string containing any text. Before performing the encryption it is a good idea to copy the data into an unsigned char pointer to avoid future problems with casts when the encryption is performed.

Finally, when using the Win32 Crypto API, please notice that it might not necessary compile as is. This is because a pre-processor definition is missing in the project.

#define _WIN32_WINNT 0x0400

When defining the above globally to the project, it will be possible to compile code that is using the Crypto API. My suggestion is to place the definition in the StdAfx.h file.

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

Share

About the Author

Jessn
Architect
Denmark Denmark
I'm an independent researcher and software architect, who holds a master's degree from Aarhus University, Denmark. I have more than 10 yrs of commercial experience. I am specialized in the C++ programming language, software architectures and crypto systems.

Support & help
https://groups.google.com/forum/#!forum/nielsen-tools-support

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionEncryption of Japanese characters Pin
uzayim3-Dec-12 11:09
memberuzayim3-Dec-12 11:09 
AnswerRe: Encryption of Japanese characters Pin
Jessn5-Dec-12 9:17
memberJessn5-Dec-12 9:17 
GeneralRe: Encryption of Japanese characters Pin
uzayim5-Dec-12 10:03
memberuzayim5-Dec-12 10:03 
QuestionDigital Certificate Pin
Daniel Ramnath23-Sep-12 8:49
memberDaniel Ramnath23-Sep-12 8:49 
Hi,

I am looking some good article, website or book which I can purchase for programming using windows digital certificate api. The MSDN doesn't seems to be of much help. Please advice me. Thank you.

Regards,

Daniel Ramnath.
Jesus saves

Bugerror in running the code Pin
Member 91308804-Jul-12 18:06
memberMember 91308804-Jul-12 18:06 
AnswerRe: error in running the code Pin
Jessn30-Jul-12 1:10
memberJessn30-Jul-12 1:10 
Generalproblem using the crypto api Pin
stylix0074-May-09 23:35
memberstylix0074-May-09 23:35 
QuestionHave bugs been fixed int his sample code? Pin
Gonzalo Parra17-Jun-08 4:55
memberGonzalo Parra17-Jun-08 4:55 
AnswerRe: Have bugs been fixed int his sample code? Pin
Jessn17-Jun-08 5:56
memberJessn17-Jun-08 5:56 
GeneralRe: Have bugs been fixed int his sample code? Pin
Gonzalo Parra17-Jun-08 7:28
memberGonzalo Parra17-Jun-08 7:28 
AnswerRe: Have bugs been fixed int his sample code? Pin
Jessn17-Jun-08 9:44
memberJessn17-Jun-08 9:44 
GeneralRe: Have bugs been fixed int his sample code? Pin
Gonzalo Parra17-Jun-08 9:53
memberGonzalo Parra17-Jun-08 9:53 
QuestionIs it possible to restrict the output characters? Pin
Angus Comber15-Jun-08 12:16
memberAngus Comber15-Jun-08 12:16 
AnswerRe: Is it possible to restrict the output characters? Pin
Jessn16-Jun-08 5:15
memberJessn16-Jun-08 5:15 
GeneralRe: problem Pin
nomicism22-Oct-07 1:15
membernomicism22-Oct-07 1:15 
GeneralRe: problem Pin
Jessn9-Dec-08 22:26
memberJessn9-Dec-08 22:26 
NewsOrigin of key data... Pin
achainard13-Oct-07 6:09
memberachainard13-Oct-07 6:09 
Questionthe key in key.h Pin
Ray Cheng17-Apr-06 22:07
memberRay Cheng17-Apr-06 22:07 
AnswerRe: the key in key.h Pin
Jessn18-Apr-06 1:56
memberJessn18-Apr-06 1:56 
QuestionRe: the key in key.h Pin
Ray Cheng18-Apr-06 18:23
memberRay Cheng18-Apr-06 18:23 
AnswerRe: the key in key.h Pin
Jessn31-May-06 2:22
memberJessn31-May-06 2:22 
GeneralRe: the key in key.h Pin
Ray Cheng8-Jun-06 5:08
memberRay Cheng8-Jun-06 5:08 
GeneralRe: the key in key.h Pin
Jessn9-Jun-06 1:04
memberJessn9-Jun-06 1:04 
GeneralBuilding Secure Applications Pin
Jessn23-Jan-06 4:30
memberJessn23-Jan-06 4:30 
QuestionHow is the code related to RSA? Pin
semmel7124-Nov-05 5:12
membersemmel7124-Nov-05 5:12 
AnswerRe: How is the code related to RSA? Pin
Jessn24-Nov-05 5:35
memberJessn24-Nov-05 5:35 
Questionsome problems with the program Pin
bbrehm0417-Nov-05 22:58
memberbbrehm0417-Nov-05 22:58 
AnswerRe: some problems with the program Pin
Jessn23-Nov-05 5:46
memberJessn23-Nov-05 5:46 
GeneralRe: some problems with the program Pin
bbrehm0423-Nov-05 21:34
memberbbrehm0423-Nov-05 21:34 
GeneralRe: some problems with the program Pin
Jessn23-Nov-05 23:57
memberJessn23-Nov-05 23:57 
GeneralRe: some problems with the program Pin
bbrehm0424-Nov-05 16:44
memberbbrehm0424-Nov-05 16:44 
GeneralRe: some problems with the program Pin
bbrehm0424-Nov-05 19:04
memberbbrehm0424-Nov-05 19:04 
GeneralRe: some problems with the program Pin
Jessn25-Nov-05 0:30
memberJessn25-Nov-05 0:30 
Questionsafe? Pin
T1TAN9-Sep-05 1:08
memberT1TAN9-Sep-05 1:08 
AnswerRe: safe? Pin
Jessn9-Sep-05 1:54
memberJessn9-Sep-05 1:54 
GeneralRe: safe? Pin
T1TAN9-Sep-05 6:33
memberT1TAN9-Sep-05 6:33 
GeneralRe: safe? Pin
Jessn10-Sep-05 3:23
memberJessn10-Sep-05 3:23 
GeneralRe: safe? Pin
T1TAN12-Sep-05 0:14
memberT1TAN12-Sep-05 0:14 
GeneralRe: safe? Pin
Jessn13-Sep-05 11:42
memberJessn13-Sep-05 11:42 
GeneralRe: safe? Pin
T1TAN14-Sep-05 0:54
memberT1TAN14-Sep-05 0:54 
GeneralRe: safe? Pin
Jessn30-Sep-05 8:11
memberJessn30-Sep-05 8:11 
GeneralRe: safe? Pin
T1TAN2-Oct-05 23:11
memberT1TAN2-Oct-05 23:11 
GeneralRe: safe? Pin
Jessn15-Oct-05 7:18
memberJessn15-Oct-05 7:18 
GeneralRe: safe? Pin
T1TAN15-Oct-05 15:43
memberT1TAN15-Oct-05 15:43 
GeneralRe: safe? Pin
Jessn17-Oct-05 19:28
memberJessn17-Oct-05 19:28 
GeneralRe: safe? [modified] Pin
Jessn28-Oct-07 22:57
memberJessn28-Oct-07 22:57 
GeneralRe: safe? Pin
T1TAN28-Oct-07 23:59
memberT1TAN28-Oct-07 23:59 
GeneralIt traps Pin
Alexander D. Alexeev9-Sep-05 0:19
memberAlexander D. Alexeev9-Sep-05 0:19 
GeneralRe: It traps Pin
Jessn9-Sep-05 0:42
memberJessn9-Sep-05 0:42 
GeneralA picky comment Pin
fwsouthern8-Sep-05 18:13
memberfwsouthern8-Sep-05 18:13 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161205.3 | Last Updated 8 Sep 2005
Article Copyright 2005 by Jessn
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid