Diffie-Hellman Keys

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 CryptAcquireContext to 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 CryptDestroyKey to destroy the key handle, HCRYPTKEY.

To generate the key by generating all new values

  • Call CryptGenKey by passing either CALG_DH_SF, store and forward, or CALG_DH_EPHEM, ephemeral, in the Algid parameter. 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 phKey parameter.

    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_BLOB structure with the pbData member set to the G value. The BLOB contains no header information and the pbData member is in little-endian format.

  2. Initialize a CRYPT_DATA_BLOB structure with the pbData member set to the P value. The BLOB contains no header information and the pbData member is in little-endian format.

  3. Call CryptGenKey passing either CALG_DH_SF, store and forward, or CALG_DH_EPHEM, ephemeral, in the Algid parameter, and CRYPT_PREGEN for the dwFlags parameter. A key handle will be generated and returned in the phKey parameter.

  4. The value of G is set by calling CryptSetKeyParam, passing the key handle that was retrieved in step 3 in the hKey parameter, the KP_G flag in the dwParam parameter, and a pointer to the structure containing the value of G in the pbData member.

  5. The value of P is set by calling CryptSetKeyParam, passing the key handle that was retrieved in step 3 in the hKey parameter, the KP_P flag in the dwParam parameter, and a pointer to the structure containing the value of P in the pbData member.

  6. The value of X is generated by calling CryptSetKeyParam, passing the key handle that was retrieved in step c in the hKey parameter, the KP_X flag in the dwParam parameter, and NULL in the pbData parameter.

    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 CryptSetKeyParam is called with KP_G or KP_P specified in the dwParam parameter. If CryptDestroyKey is 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 CryptAcquireContext to get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.
  2. Get a handle to a DIFFIE-HELLMAN key by calling CryptGenKey to create a new key, or by calling CryptGetUserKey to retrieve an existing one.
  3. Get the memory byte length needed to hold a DIFFIE-HELLMAN 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 DIFFIE-HELLMAN public-key BLOB by calling CryptExportKey, passing both PUBLICKEYBLOB in the dwBlobType parameter and the handle to the DIFFIE-HELLMAN key in the hKey parameter. 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 CryptAcquireContext to get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.

  2. Get a handle to a DIFFIE-HELLMAN key by calling CryptGenKey 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 DIFFIE-HELLMAN key in the hPubKey parameter. This call to CryptImportKey causes 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 hKey parameter.

  4. Convert the shared, secret key to the CALG_RC4, bulk-encryption key type, by calling CryptSetKeyParam with dwParam set to KP_ALGID, and with pbData set to a pointer to CALG_RC4. 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 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 CryptDestroyKey to 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 CryptAcquireContext to get a handle to the Microsoft Diffie-Hellman Cryptographic Provider.
  2. Get a handle to a DIFFIE-HELLMAN key by calling CryptGenKey to create a new key, or by calling CryptGetUserKey to retrieve an existing one.
  3. Create a Diffie-Hellman public-key BLOB by calling CryptExportKey, passing both PRIVATEKEYBLOB in the dwBlobType parameter and the handle to the DIFFIE-HELLMAN key in the hKey parameter.
  4. When the key is no longer needed, call CryptDestroyKey to destroy the key handle (HCRYPTKEY).

See Also

CryptAcquireContext | CryptDecrypt | CryptDestroyKey | CryptEncrypt | CryptExportKey | CryptGenKey | CryptGetKeyParam | CryptGetUserKey | CryptGetUserKey | ALG_ID | CRYPT_DATA_BLOB | HCRYPTKEY

 Last updated on Thursday, April 08, 2004

© 1992-2003 Microsoft Corporation. All rights reserved.