Exchanging Diffie-Hellman Keys
The purpose of the Diffie-Hellman algorithm is to make it possible for two or more hosts to create and share an identical, secret encryption key by simply sharing information over an insecure network. The information that gets shared over the network is in the form of a couple of constant values, and a D-H public key. The process used by two key-exchange participants is as follows:
-
Both participants agree to the "Diffie-Hellman parameters," a prime number (P), and a base number (G).
-
Participant 1 sends its D-H public key to participant 2.
-
Participant 2 computes the secret encryption key by using the information contained in participant 1's public key.
-
Participant 2 sends participant 1 its D-H public key.
-
Participant 1 computes the secret encryption key by using the information contained in participant 2's public key.
-
Both participants now have the same encryption key, which can be used for encrypting and decrypting data. The steps necessary for this are shown in the following procedure.
To prepare a Diffie-Hellman public key for transmission
-
Get a handle to the Diffie-Hellman provider.
-
Get a handle to a D-H key. This can be done by calling CryptGenKey (see Generating Diffie-Hellman Keys) to create a new key, or by calling CryptGetUserKey to retrieve an existing one.
-
Get the memory length (in bytes) needed to hold a D-H key by calling CryptExportKey, passing NULL for the pbData parameter. The key length will be returned in pdwDataLen.
-
Allocate memory for the key.
-
Create a D-H public-key blob by calling CryptExportKey, passing PUBLICKEYBLOB in the dwBlobType parameter and the handle to the D-H key in the hKey parameter. This function call causes the calculation of the public key value, (G^X) mod P. If all the preceding function calls were successful, the D-H public key is now ready to be encoded and transmitted.
To import a D-H public key and calculate the private (secret) key
-
Get a handle to the Diffie-Hellman provider.
-
Get a handle to a D-H key. This can be done by calling CryptGenKey (see Generating Diffie-Hellman Keys) to create a new key, or by calling CryptGetUserKey to retrieve an existing one.
-
To import the key into the CSP, call CryptImportKey, passing a pointer to the public key blob in the pbData parameter, the length of the blob in the dwDataLen parameter, and the handle to the D-H key in the hPubKey parameter. This call to CryptImportKey causes the calculation, (Y^X) mod P, to be performed thus creating the shared, secret key and completing the key exchange. This function call returns a handle to the new, secret, bulk-encryption key in the hKey parameter.
-
Convert the shared, secret key to the CALG_CYLINK_MEK, bulk-encryption key type, by calling CryptSetKeyParam with dwParam set to KP_ALGID, and with pbData set to a pointer to CALG_CYLINK_MEK. This step must be done before using the shared key in CryptEncrypt or CryptDecrypt. Calls made to either of these functions prior to calling CryptSetKeyParam will fail.
If a call to CryptGetKeyParam is made on the key handle returned from the call to CryptImportKey and prior to calling CryptSetKeyParam (as described in this step), the ALG_ID returned by the call to CryptGetKeyParam will be CALG_AGREEDKEY_ANY. If all the preceding function calls were successful, the secret key is now ready to be used for encryption or decryption.
-
When finished with the key, call CryptDestroyKey to destroy the handle (HCRYPTKEY) to the key.