CryptDeriveKey

The CryptDeriveKey function generates cryptographic keys derived from base data. This function guarantees that all keys generated from the same base data will be identical, provided the same CSP and algorithms are used. The base data can be a password or any other user data.

This function is the same as CryptGenKey, except that the generated session keys are derived from base data instead of being random. Another difference is that the CryptDeriveKey function cannot be used to generate public/private key pairs.

A handle to the session key is returned in phKey. This handle can then be used as needed with any of the other CryptoAPI functions that require key handles.

#include <wincrypt.h>
BOOL WINAPI CryptDeriveKey(
  HCRYPTPROV hProv,      // in
  ALG_ID Algid,          // in
  HCRYPTHASH hBaseData,  // in
  DWORD dwFlags,         // in
  HCRYPTKEY *phKey       // in/out
);
 

Parameters

hProv
A handle to the application's CSP. An application obtains this handle by using the CryptAcquireContext function.
Algid
The identifier for the algorithm for which the key is to be generated.

The valid values for this parameter will vary, depending on the CSP that is used. See the "Remarks" section for a list of possible algorithm identifiers.

hBaseData
A handle to a hash object that has been fed the exact base data.

To obtain this handle, an application must first create a hash object with CryptCreateHash and then add the base data to the hash object with CryptHashData. This process is described in detail in Hashes and Digital Signatures.

dwFlags
The flags specifying the type of key generated. This parameter can be zero, or you can specify one or more of the following flags by using the bitwise OR operator to combine them:
phKey
The address to which the function copies the handle of the newly generated key.

Return Values

If the function succeeds, the return value is TRUE. If it fails, the return value is FALSE. To retrieve extended error information, use the GetLastError function.

The following table lists the error codes most commonly returned by the GetLastError function. The error codes prefaced by "NTE" are generated by the particular CSP you are using.

Error code Description
ERROR_INVALID_HANDLE One of the parameters specifies an invalid handle.
ERROR_INVALID_PARAMETER One of the parameters contains an invalid value. This is most often an illegal pointer.
NTE_BAD_ALGID The Algid parameter specifies an algorithm that this CSP does not support.
NTE_BAD_FLAGS The dwFlags parameter contains an invalid value.
NTE_BAD_HASH The hBaseData parameter does not contain a valid handle to a hash object.
NTE_BAD_HASH_STATE An attempt was made to add data to a hash object that is already marked "finished."
NTE_BAD_UID The hProv parameter does not contain a valid context handle.
NTE_FAIL The function failed in some unexpected way.

Remarks

To generate a key for a symmetric encryption algorithm, use the Algid parameter to specify the algorithm. The algorithms available will most likely be different for each CSP. If you are using the Microsoft Base Cryptographic Provider, use one of the following values to specify the algorithm.

Value Description
CALG_RC2 RC2 block cipher
CALG_RC4 RC4 stream cipher

When keys are generated for symmetric block ciphers, the key by default will be set up in cipher block chaining (CBC) mode with an initialization vector of zero. This cipher mode provides a good default method for bulk-encrypting data. To change these parameters, use the CryptSetKeyParam function.

After the CryptDeriveKey function has been called, no more data can be added to the hash object. The CryptDestroyHash function should be called at this point to destroy the hash object.

Example

#include <wincrypt.h>

HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
CHAR szPassword[ ] = "apple-camshaft";
DWORD dwLength;

// Get a handle to user default provider.
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
    printf("Error %x during CryptAcquireContext!\n", GetLastError());
    goto done;
}

// Create a hash object.
if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
    printf("Error %x during CryptCreateHash!\n", GetLastError());
    goto done;
}

// Hash the password string.
dwLength = strlen(szPassword);
if(!CryptHashData(hHash, (BYTE *)szPassword, dwLength, 0)) {
    printf("Error %x during CryptHashData!\n", GetLastError());
    goto done;
}

// Create a block cipher session key based on the hash of the password.
if(!CryptDeriveKey(hProv, CALG_RC2, hHash, CRYPT_EXPORTABLE, &hKey)) {
    printf("Error %x during CryptDeriveKey!\n", GetLastError());
    goto done;
}

// Use 'hKey' to encrypt or decrypt a message.
...

done:

// Destroy the hash object.
if(hHash != 0) CryptDestroyHash(hHash);

// Destroy the session key.
if(hKey != 0) CryptDestroyKey(hKey);

// Release the provider handle.
if(hProv != 0) CryptReleaseContext(hProv, 0);
 

QuickInfo

  Windows NT: Requires version 4.0 or later.
  Windows: Requires Windows 95 OSR2 or later (or Windows 95 with IE 3.02 or later).
  Windows CE: Unsupported.
  Header: Declared in wincrypt.h.
  Import Library: Use advapi32.lib.

See Also

CryptAcquireContext, CryptCreateHash, CryptDestroyHash, CryptDestroyKey, CryptExportKey, CryptGenKey, CryptGetKeyParam, CryptHashData, CryptSetKeyParam