Generating Diffie-Hellman/Schannel Keys

    To generate a Diffie-Hellman public key
  1. Get a handle to the Diffie-Hellman provider.
  2. Generate the new key. There are two ways to accomplish this, by having CryptoAPI generate new values for G, P, and X, or by using existing values for G and P, and generating a new value for X.

    To generate the key by generating all new values:

    Call CryptGenKey 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, 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 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. It should contain no header information and should be little endian format.
    2. Initialize a CRYPT_DATA_BLOB structure with the pbData member set to the P value. It should contain no header information and should be 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 may be set by calling CryptSetKeyParam, passing the key handle (retrieved in step c) 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 parameter.
    5. The value of P may be set by calling CryptSetKeyParam, passing the key handle (retrieved in step c) 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 parameter.
    6. The value of X must be generated by calling CryptSetKeyParam, passing the key handle (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 D-H public key is ready for use.

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

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 CSPs may have hard coded G and P values. In this case a 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.