Important:
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
A version of this page is also available for
4/8/2010

The following procedures show the steps to generate, exchange, and export Diffie-Hellman Keys.

Generating Diffie-Hellman Keys

The following procedure shows the steps necessary to generate Diffie-Hellman keys.

To generate a Diffie-Hellman public key
  1. Call CryptAcquireContextto get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.

  2. Generate the new key. There are two ways to accomplish this: Either have CryptoAPI generate all new values for G, P, and X, or use the existing values for G and P, and generating a new value for X.

  3. When the key is no longer needed, call CryptDestroyKeyto destroy the key handle, HCRYPTKEY.

To generate the key by generating all new values
  • Call CryptGenKeyby passing either CALG_DH_SF, store and forward, or CALG_DH_EPHEM, ephemeral, in the Algidparameter. The key will be generated, using new, random values for G and P, and a newly calculated value for X, and its handle will be returned in the phKeyparameter.

    The new key is now ready for use. Note that the values of G and P must be sent along with the key, or sent by some other method, when the application is doing a key exchange.

To generate the key by using predefined values for G and P
  1. Initialize a CRYPT_DATA_BLOBstructure with the pbDatamember set to the G value. The BLOB contains no header information and the pbDatamember is in little-endian format.

  2. Initialize a CRYPT_DATA_BLOBstructure with the pbDatamember set to the P value. The BLOB contains no header information and the pbDatamember is in little-endian format.

  3. Call CryptGenKeypassing either CALG_DH_SF, store and forward, or CALG_DH_EPHEM, ephemeral, in the Algidparameter, and CRYPT_PREGEN for the dwFlagsparameter. A key handle will be generated and returned in the phKeyparameter.

  4. The value of G is set by calling CryptSetKeyParam, passing the key handle that was retrieved in step 3 in the hKeyparameter, the KP_G flag in the dwParamparameter, and a pointer to the structure containing the value of G in the pbDatamember.

  5. The value of P is set by calling CryptSetKeyParam, passing the key handle that was retrieved in step 3 in the hKeyparameter, the KP_P flag in the dwParamparameter, and a pointer to the structure containing the value of P in the pbDatamember.

  6. The value of X is generated by calling CryptSetKeyParam, passing the key handle that was retrieved in step c in the hKeyparameter, the KP_X flag in the dwParamparameter, and NULL in the pbDataparameter.

    If all the function calls succeeded, the DIFFIE-HELLMAN public key is ready for use.

If CALG_DH_SF was specified in the previous procedures, the key values are persisted to storage with each call to CryptSetKeyParam. The G and P values can then be retrieved using CryptGetKeyParam. Some cryptographic service providers may have hard-coded G and P values. In this case an NTE_FIXEDPARAMETERS error will be returned if CryptSetKeyParamis called with KP_G or KP_P specified in the dwParamparameter. If CryptDestroyKeyis called, the handle to the key is destroyed, but the key values are retained in the CSP. However, if CALG_DH_EPHEM was specified, the handle to the key is destroyed and all values are purged from the CSP.

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 simply by sharing information over an unsecure network. The information that gets shared over the network is in the form of two constant values, and a DIFFIE-HELLMAN public key. The following list shows the process that is used by two key-exchange participants:

  1. Both participants agree to the "Diffie-Hellman parameters," a prime number (P), and a base number (G).

  2. Participant 1 sends its DIFFIE-HELLMAN public key to participant 2.

  3. Participant 2 computes the secret encryption key by using the information contained in participant 1's public key.

  4. Participant 2 sends participant 1 its DIFFIE-HELLMAN public key.

  5. Participant 1 computes the secret encryption key by using the information contained in participant 2's public key.

  6. Both participants now have the same encryption key, which can be used for encrypting and decrypting data.

The steps necessary to complete this process are shown in the following procedure.

To prepare a Diffie-Hellman public key for transmission
  1. Call CryptAcquireContextto get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.

  2. Get a handle to a DIFFIE-HELLMAN key by calling CryptGenKeyto create a new key, or by calling CryptGetUserKeyto retrieve an existing one.

  3. Get the memory byte length needed to hold a DIFFIE-HELLMAN key by calling CryptExportKey, passing NULL for the pbDataparameter. The key length will be returned in pdwDataLen.

  4. Allocate memory for the key.

  5. Create a DIFFIE-HELLMAN public-key BLOB by calling CryptExportKey, passing both PUBLICKEYBLOB in the dwBlobTypeparameter and the handle to the DIFFIE-HELLMAN key in the hKeyparameter. This function call causes the calculation of the public key value, (G^X) mod P. If all of the preceding function calls were successful, the DIFFIE-HELLMAN public key is now ready to be encoded and transmitted.

To import a DIFFIE-HELLMAN public key and calculate the private or secret key
  1. Call CryptAcquireContextto get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.

  2. Get a handle to a DIFFIE-HELLMAN key by calling CryptGenKeyto create a new key, or by calling CryptGetUserKeyto retrieve an existing one.

  3. To import the key into the CSP, call CryptImportKey, passing a pointer to the public key BLOB in the pbDataparameter, the length of the BLOB in the dwDataLenparameter, and the handle to the DIFFIE-HELLMAN key in the hPubKeyparameter. This call to CryptImportKeycauses the calculation, (Y^X) mod P, to be performed. This calculation creates the shared, secret key and completes the key exchange. This function call returns a handle to the new, secret, bulk-encryption key in the hKeyparameter.

  4. Convert the shared, secret key to the CALG_RC4, bulk-encryption key type, by calling CryptSetKeyParamwith dwParamset to KP_ALGID, and with pbDataset to a pointer to CALG_RC4. This step must be done before using the shared key in CryptEncryptor CryptDecrypt. Calls made to either of these functions prior to calling CryptSetKeyParamwill fail.

    If a call to CryptGetKeyParamis made on the key handle returned from the call to CryptImportKeyand prior to calling CryptSetKeyParam, as described in this step, the ALG_IDreturned by the call to CryptGetKeyParamwill be CALG_AGREEDKEY_ANY. If all of the preceding function calls were successful, the secret key is now ready to be used for encryption or decryption.

  5. When the key is no longer needed, call CryptDestroyKeyto destroy the key handle ( HCRYPTKEY).

Exporting a Diffie-Hellman Private or Secret Key

The steps necessary to export a Diffie-Hellman private key are shown in the following procedure.

To export a DIFFIE-HELLMAN private key
  1. Call CryptAcquireContextto get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.

  2. Get a handle to a DIFFIE-HELLMAN key by calling CryptGenKeyto create a new key, or by calling CryptGetUserKeyto retrieve an existing one.

  3. Create a Diffie-Hellman public-key BLOB by calling CryptExportKey, passing both PRIVATEKEYBLOB in the dwBlobTypeparameter and the handle to the DIFFIE-HELLMAN key in the hKeyparameter.

  4. When the key is no longer needed, call CryptDestroyKeyto destroy the key handle ( HCRYPTKEY).

See Also