Using the CryptoAPI for Public/Private Data Exchange

.

With the proliferation of the Internet and enterprise applications that communicate over it, security has become a huge issue. SSL keeps Web pages secure, but how about an application that can't use SSL? What methods are available to application developers who want to keep the transfer of data secure? If you're looking for a way to keep you application's communications secure, the Microsoft CryptoAPI might be just the thing. In this article I show you how to use it and show a simple example to illustrate the salient points.

Cryptography Types

Almost all cryptography algorithms fall into one of two distinct categories: symmetric or public-key cryptography. Because these two categories encompass the vast majority of cryptography systems in use today, we should spend some time discussing the differences between the two types of algorithms.

Symmetric Algorithms

The family of algorithms classified as symmetric algorithms are the oldest and most common of the two types. In fact, when most people think of cryptography, they think of symmetric algorithms, whether they realize it or not. Symmetric algorithms are based on an encryption operation that allows the ciphertext (data that has been encrypted) to be decrypted by simply "rolling back" the encryption operation. A simple substitution scheme illustrates this.

For the sake of example, let's assume the following message needs to be encrypted:

HARRY-GUARDS ARE AT THE CONSULATE. MEET ME AT THE DOCKS AT 11:45 TONIGHT.

Now let's assume the encryption key is the number 5. The algorithm shifts each letter five letters to the right so that the ciphertext looks like this:

MFWW4-LZFWIX FWJFY YMJ HTSXZQFYJ. RJJY RJ FY YMJ ITHPX FY 66:90 YTSNLMY.

It doesn't look much like the original. Because this is a symmetric algorithm, all that is required to decrypt the data is to roll back the encryption operation. In this case, all we need do is shift each character of the ciphertext five letters to the left to recover the data.

The symmetric properties of this algorithm make it very easy to understand and use. It is this simplicity that also makes substitution schemes like this very insecure.

Public-Key Cryptography

The other group of widely used algorithms is referred to as public-key, or asymmetric algorithms. The strength of this  family of algorithms relies on the fact that the encryption key and decryption key have nothing in common. In other words, if I possessed both a ciphertext message and the decryption key, I would not be able to derive the encryption key. This unique attribute of the encrypt and decrypt keys also makes public-key cryptography well suited to a number of additional applications besides data encryption. Public-key cryptography is used to provide digital signatures for SSL.

Let's say you possess two keys. One key is kept private and is used by you to decrypt data. The other key is widely published and can be used by anyone to encrypt messages that only you can decrypt with you r privately held key. These keys are commonly referred to as private and public keys. A private key can only decrypt information that has been encrypted with its matching public key. No one intercepting the message can decrypt it, and you don't have to pass your private key to anyone for then to send you an encrypted message.

When you send a message, such as an email or Usenet newsgroup posting, you can "sign" the end of your message by computing a combination of your private key and the message itself. People who posses a copy of your public key can use it to determine the validity of the signature. If they can properly interpret the digital signature, they can be sure the message came from you and wasn't altered in transit.

Public-key cryptography is based on some rather complex mathematics that deal with one-way hash functions. rolling back the operation of a one-way hash function is extremely difficult. So difficult, in fact, that even on very powerful computers, such as Cray mainframes, it would take hundreds of thousands of years to discover the encryption key. The hash function operates in the "easy" direction when it is encrypting data. We will discuss hash functions in the next section. For now, just remember that a one-way hash function is a mathematical operation which is very difficult to roll back. As the function processes each chunk of plain text, it is generating hash valies. In order to decrypt the data and roll the operation back, you would need to know a vital piece of information about the function. This is the private key.

Hash Functions

Let's move away from our high-level overview and consider one of the basic building blocks for most secure cryptographic algorithms: the hash function. Strictly speaking, a hash function takes variable length data, such as a text message, and performs one or more mathematical operations to convert the variable length data into a fixed length format.

Hash functions are used not only in cryptography, but also in many other areas of computer science such as checksums and compiler technology. Hash functions are handy things indeed. Hash functions are so useful because the function creates a "fingerprint" of the data, or plain text, it processes. The fingerprint is normally expressed as a number -- which computers are very good at understanding.

As an example, let's compute a very simple hash function, using the string "apple". Our function will use the ASCII values of each character to compute the hash value, as follows:

Character ASCII Value ASCII Value Mod 23
a 97 5
p 112 20
p 112 20
l 108 16
e 101 9

The hash value is computed by taking the ASCII value mod 23. The number 23 was selected because it is a prime number and would produce a relatively unique hash. The hash value for this string is simply the sum of the third column. In our example, the hash value is 70. The hash value 70 now represents the word "apple".

Our simple hash function is not a very good hash function because it would produce many hash collisions. A hash collision is when two different strings produce the same hash value. Collisions reduce the usefulness and effectiveness of the function because collisions introduce uncertainty when interpreting the results. A good hash function is designed to produce a minimal number of collisions.

Researching hash functions is a popular field of study within the mathematics community. Many mathematicians spend much of their careers investigating the properties of new and existing hash functions. Part of the popularity of hash functions can be attributed to their wide range of applications, including cryptography.

Many of the world's most secure cryptographic algorithms rely on very strong hash functions. These functions are so strong that they are often termed one-way hash functions. This means there is no easy way to deduce the input value of the function from the output value, Most functions of this type operate on groups of bits rather than whole characters. Operating at such a low level allows the hash function to escape from difficulties such as character-frequency problems.

Microsoft's CryptoAPI

In an attempt to make cryptography more widespread and easier for us normal mortals to use in our applications, Microsoft has designed and released a cryptography API for the Win32 platforms. It is called CryptoAPI.

CryptoAPI is organized in a modular fashion. Encryption and decryption services are provided by modules called Cryptographic Service Providers (CSP). These modules are responsible for implementing different encryption schemes as well as guaranteeing the security of the encryption/decryption process. Microsoft has also release a CSP SDK for persons interested in developing their own CSPs. This information can be accessed at http://www.microsoft.com/security.

For now, let's look at the structure of CryptoAPI. The API can be dissected into four discrete sections: key functions, encryption/decryption functions, hashing functions, and CSP functions. We will cover the sections of most interst to us: key functions and encryption/decryption.

Before you can write any code to use the CryptoAPI, you must establish a set of cryptographic keys for the user and configure a default CSP. If you skip this step, your calls to CryptoAPI will fail. Microsoft provides the source code to  utility that sets up the crypto environment. The utility is called inituser.exe and accompanies MSDN. The following code can be added to your program to perform the same action as inituser.exe. This may be better than expecting users to run the inituser.exe utility, especially if this is an application meant for widespread distribution.

A function to initialize the crypto settings for a user.
#define _WIN32_WINNT 0x0400
#include "wincrypt.h"
#define ENCRYPT_BLOCK_SIZE 1
#define ENCRYPT_ALGORITHM CALG_RC4

void InitUser( void )
{ 
 HCRYPTPROV hProv;
 HCRYPTKEY hKey;
 CHAR szUserName[100];
 DWORD dwUserNameLen = sizeof( szUserName );

 // Attempt to acquire a handle to the default key container. 
 if( !CryptAcquireContext( &hProv, 
                           NULL, 
                           MS_DEF_PROV, 
                           PROV_RSA_FULL, 
                           0 ) )
 {
  // Some sort of error occured. 

  // Create default key container. 
  if( !CryptAcquireContext( &hProv, 
                            NULL, 
                            MS_DEF_PROV, 
                            PROV_RSA_FULL, 
                            CRYPT_NEWKEYSET ) )
   return;

  // Get name of default key container. 
  if( !CryptGetProvParam( hProv, 
                          PP_CONTAINER, 
                          (unsigned char *) szUserName, 
                          &dwUserNameLen, 0 ) )
   // Error getting key container name. 
   szUserName[0] = 0; 
 } 

 // Attempt to get handle to signature key. 
 if( !CryptGetUserKey( hProv, AT_SIGNATURE, &hKey ) )
 {
  if( GetLastError() == NTE_NO_KEY )
  {
   // Create signature key pair. 
   if( !CryptGenKey( hProv, AT_SIGNATURE, 0, &hKey ) )
    return;
   else
    CryptDestroyKey( hKey );
  }
  else
   return;
 }
 
 // Attempt to get handle to exchange key. 
 if( !CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hKey ) )
 {
  if( GetLastError() == NTE_NO_KEY )
  {
   // Create key exchange key pair. 

   if( !CryptGenKey( hProv, AT_KEYEXCHANGE, 0, &hKey ) )
    return;
   else
    CryptDestroyKey( hKey );
   }
  else
   return;
 }

 CryptReleaseContext( hProv, 0 );
} 

The Demo Application

The demo application is in two parts. One part is an ISAPI DLL (named CryptoAPI_Auth.dll) that resides on a Web server, and the other part is an executable program (named ClientDemo.exe) that resides on a client machine. Note that the DLL compiles to a file named ApplicationAuth.dll. It was named CryptoAPI_Auth.dll before being copied to the Web server for this demo just so that the file naming convention on the sourceDNA.com server would remain consistent. The DLL contains a list of three user names and passwords as follows:

User ID Password
JOHNPUBLIC MYSELF
JANEDOE COMPUTER
SAMSMITH TENNIS

Ordinarily, user IDs and passwords would be kept in some sort of database. To keep the demo focused on the topic at hand, I just used an array of data structures to hold them.

The way the demo works is this:
1. A user runs the client application.
2. The user types in the User ID and Password.
3. The user clicks on the Submit button.
4. The client application sends the User ID to the DLL with an Http request. (The User ID is the public key).
5. The DLL gets the User ID, checks to make sure it's in the list, and returns a random number. Normally the random number is saved to a database for later use. Since there is no database, the random number resides in the array of data structures in which the User ID and Password exist. The random numbers are hard-coded for simplicity.
6. The client application uses the random number it gets from the DLL to encode the User ID and Password (the private key) and send the encoded data back to the DLL. (The encrypted value is the hash.) The unencrypted User ID is sent at the same time to the DLL.
7. The DLL decodes the response by looking up and using the random number it originally sent.
8. The decoded response is checked and the validity of the password is verified. Success or Error are returned. You can see the client application in Figure 1.


Figure 1: The client application after password verticiation.

Conclusion

Now that you have world-class data encryption/decryption in your arsenal, you'll be surprised how many times a use for it will arise. And if you do any contract programming, you'll be surprised at how many clients will want you to use the technology.

Microsoft makes it easy to use with the API they've provided. Now all you have to do is supply the imagination to use it in effective ways.

Downloads

Download demo - 16 Kb


Comments

  • [Q] Get public key handle

    Posted by Legacy on 11/12/2001 12:00am

    Originally posted by: HoJin Park

    How to get public key from certificate.
    plz...*^^*


    for instance...

    HCRYPTKEY CMyDemoDlg::GetPublicKey(PCCERT_CONTEXT pCertContext)
    {
    HCRYPTKEY hKey;
    .
    . <-- How to ?
    .
    return hKey;
    }

    plz...

    Reply
  • Key Size

    Posted by Legacy on 09/30/2001 12:00am

    Originally posted by: Chris

    From the MSDN CryptDeriveKey manual page:

    dwFlags
    [in] Specifies the type of key generated.
    The sizes of a session key can be set when the key is generated. The key size, representing the length of the key modulus in bits, is set with the upper 16 bits of this parameter. Thus, if a 128-bit RC4 session key is to be generated, the value 0x00800000 is combined with any other dwFlags predefined value with a bitwise-OR operation. Due to changing export control restrictions, the default CSP and default key length may change between operating system releases. It is important that both the encryption and decryption use the same CSP and that the key length be explicitly set using the dwFlags parameter to ensure interoperability on different operating system platforms.

    The lower 16 bits of this parameter can be zero or you can specify one or more of the following flags by using the bitwise-OR operator to combine them.

    Reply
  • Distriburion

    Posted by Legacy on 04/15/2001 12:00am

    Originally posted by: lamer2000

    Is Crypto API redistributable without Internet Explorer? If yes, can third party ships it with wheir products?

    Reply
  • So you exchange clearly the random number on the network

    Posted by Legacy on 04/10/2001 12:00am

    Originally posted by: softlion

    That's better than exchanging clear password,
    but that's not nice...

    Why not use the existing Private Key Exchange alorithm ?

    Reply
  • Win32 Client/UNIX Server

    Posted by Legacy on 04/08/2001 12:00am

    Originally posted by: Gerard Nicol

    Is the Win32 crypto API compliant with any libraries available for UNIX/Linux?

    Reply
  • 53 Byte limit in Public/Private key system?

    Posted by Legacy on 04/05/2001 12:00am

    Originally posted by: Matt

    Is there a 53 (64-11) byte limitation to the amount of data you can encrypt when using a public/private key system?

    If found that all's working until I hit 54 bytes. Then CryptEncrypt returns false and GetLastError returns 0x80090004 which means basically means "Bad length".

    For now, I'm encrypting in 53 byte chunks to get around this problem.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • On-demand Event Event Date: October 23, 2014 Despite the current "virtualize everything" mentality, there are advantages to utilizing physical hardware for certain tasks. This is especially true for backups. In many cases, it is clearly in an organization's best interest to make use of physical, purpose-built backup appliances rather than relying on virtual backup software (VBA - Virtual Backup Appliances). Join us for this webcast to learn why physical appliances are preferable to virtual backup appliances, …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds