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:

    To prepare a Diffie-Hellman public key for transmission
  1. Get a handle to the Diffie-Hellman provider.
  2. 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.
  3. 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.
  4. Allocate memory for the key.
  5. 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
  1. Get a handle to the Diffie-Hellman provider.
  2. 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.
  3. 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.
  4. 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.

  5. When finished with the key, call CryptDestroyKey to destroy the handle (HCRYPTKEY) to the key.