CryptDeriveKey 函数 (wincrypt.h)

重要 此 API 已弃用。 新的和现有的软件应开始使用 加密下一代 API。 Microsoft 可能会在将来的版本中删除此 API。
 
CryptDeriveKey 函数生成从基数据值派生 的加密 会话密钥。 此函数可确保使用相同的 加密服务提供程序(CSP)和算法时,从同一基本数据生成的密钥是相同的。 基本数据可以是密码或任何其他用户数据。

此函数与 CryptGenKey相同,不同之处在于生成的 会话键 派生自基数据而不是随机密钥。 CryptDeriveKey 只能用于生成会话密钥。 它无法生成 公钥/私钥对。

phKey 参数中返回会话密钥的句柄。 此句柄可与需要密钥句柄的任何 CryptoAPI 函数一起使用。

语法

BOOL CryptDeriveKey(
  [in]      HCRYPTPROV hProv,
  [in]      ALG_ID     Algid,
  [in]      HCRYPTHASH hBaseData,
  [in]      DWORD      dwFlags,
  [in, out] HCRYPTKEY  *phKey
);

参数

[in] hProv

调用 CryptAcquireContext创建的 CSP HCRYPTPROV 句柄。

[in] Algid

一个 ALG_ID 结构,用于标识要为其生成密钥的 对称加密 算法。 对于每个 CSP,可用的算法很可能有所不同。 有关密钥规格AT_KEYEXCHANGE和AT_SIGNATURE的不同提供程序使用哪些算法标识符的详细信息,请参阅 ALG_ID

有关 ALG_ID 值与 Microsoft 基本加密提供程序一起使用的详细信息,请参阅 基提供程序算法。 有关 ALG_ID 值与Microsoft强加密提供程序或Microsoft增强加密提供程序一起使用的详细信息,请参阅 增强提供程序算法

[in] hBaseData

哈希对象的句柄, 已馈送确切的基数据。

若要获取此句柄,应用程序必须首先使用 CryptCreateHash 创建哈希对象,然后使用 CryptHashData将基数据添加到哈希对象。 此过程在 哈希和数字签名中进行了详细介绍。

[in] dwFlags

指定生成的密钥的类型。

生成密钥时可以设置会话密钥的大小。 键大小(以位为单位表示键模数的长度)是用此参数的 16 位设置的。 因此,如果要生成 128 位 RC4 会话密钥,则值0x00800000将与其他任何 dwFlags 结合使用, 预定义值以及按位OR 操作。 由于更改导出控制限制,默认 CSP 和默认 密钥长度 可能会在操作系统版本之间更改。 加密和解密都必须使用相同的 CSP,并且使用 dwFlags 参数显式设置密钥长度,以确保在不同操作系统平台上实现互操作性。

此参数的低 16 位可以是零,也可以使用按位OR 运算符来指定以下一个或多个标志。

价值 意义
CRYPT_CREATE_SALT
通常,当会话键从 哈希 值生成时,会有一些剩余位。 例如,如果哈希值为 128 位,并且会话键为 40 位,则剩余 88 位。

如果设置了此标志,则会根据未使用的哈希值位为密钥分配 盐值。 可以使用 CryptGetKeyParam 函数,并将 dwParam 参数设置为KP_SALT来检索此 值。

如果未设置此标志,则为键指定为零的盐值。

导出具有非零盐值的键(通过使用 CryptExportKey),还必须获取并保留 密钥 BLOB的盐值。

CRYPT_EXPORTABLE
如果设置了此标志,可以通过 CryptExportKey 函数将会话密钥从 CSP 传输到密钥 BLOB。 由于密钥通常必须可导出,因此通常应设置此标志。

如果未设置此标志,则会话密钥不可导出。 这意味着密钥仅在当前会话中可用,并且只有创建密钥的应用程序才能使用它。

此标志不适用于公钥/私钥对。

CRYPT_NO_SALT
此标志指定为 40 位 对称密钥分配无 值。 有关详细信息,请参阅 Salt Value 功能
CRYPT_UPDATE_KEY
某些 CSP 使用从多个哈希值派生的会话密钥。 在这种情况下,必须多次调用 CryptDeriveKey

如果设置了此标志,则不会生成新的会话密钥。 而是修改由 phKey 指定的键。 此标志的精确行为取决于要生成的密钥的类型以及正在使用的特定 CSP。

Microsoft加密服务提供商忽略此标志。

CRYPT_SERVER
1024 (0x400)
此标志仅用于 Schannel 提供程序。 如果设置了此标志,则要生成的密钥是服务器写入密钥;否则,它是客户端写入密钥。

[in, out] phKey

指向 HCRYPTKEY 变量的指针,用于接收新生成的密钥句柄的地址。 使用完密钥后,通过调用 CryptDestroyKey 函数释放句柄。

返回值

如果函数成功,该函数将返回非零(TRUE)。

如果函数失败,则返回零(FALSE)。 有关扩展错误信息,请调用 GetLastError

“NTE”开头的错误代码由正在使用的特定 CSP 生成。 下表列出了一些可能的错误代码。

返回代码 描述
ERROR_INVALID_HANDLE
其中一个参数指定无效的句柄。
ERROR_INVALID_PARAMETER
其中一个参数包含无效的值。 这通常是无效的指针。
NTE_BAD_ALGID
Algid 参数指定此 CSP 不支持的算法。
NTE_BAD_FLAGS
dwFlags 参数包含无效的值。
NTE_BAD_HASH
hBaseData 参数不包含对 哈希对象的有效句柄。
NTE_BAD_HASH_STATE
尝试将数据添加到已标记为“已完成”的哈希对象。
NTE_BAD_UID
hProv 参数不包含有效的上下文句柄。
NTE_FAIL
函数以某种意外的方式失败。
NTE_SILENT_CONTEXT
提供程序无法执行该操作,因为上下文是以无提示方式获取的。

言论

对称块密码生成密钥时,默认情况下,密钥在 密码块链(CBC)模式下设置,初始化向量为零。 此 密码模式 为批量加密数据提供了良好的默认方法。 若要更改这些参数,请使用 CryptSetKeyParam 函数。

CryptDeriveKey 函数完成 哈希。 调用 CryptDeriveKey 后,无法向哈希添加更多数据。 对 CryptHashDataCryptHashSessionKey 的其他调用失败。 使用哈希完成应用程序后,必须调用 CryptDestroyHash 来销毁哈希对象。

若要选择适当的 密钥长度,建议使用以下方法。

  • 若要枚举 CSP 支持的算法,并获取每个算法的最大和最小密钥长度,请使用 PP_ENUMALGS_EX 调用 CryptGetProvParam
  • 使用最小和最大长度选择适当的密钥长度。 不建议选择最大长度,因为这可能会导致性能问题。
  • 选择所需的密钥长度后,请使用 dwFlags 参数的上限 16 位来指定密钥长度。
n 为所需的派生密钥长度(以字节为单位)。 派生密钥是 CryptDeriveKey完成哈希计算后哈希值的第一个 n 字节。 如果哈希不是 SHA-2 系列的成员,并且所需的密钥适用于 3DES 或 AES,则密钥派生如下:
  1. 通过重复常量 0x36 64 次,形成 64 字节缓冲区。 k 是由输入参数 hBaseData表示的哈希值的长度。 将缓冲区的第一个 k 字节设置为 XOR 运算的结果,该 k 字节的缓冲区的第一个 个字节,其哈希值由输入参数 hBaseData表示。
  2. 通过重复常量 0x5C 64 次,形成 64 字节缓冲区。 将缓冲区的第一个 k 字节设置为 XOR 运算的结果,该 k 字节的缓冲区的第一个 个字节,其哈希值由输入参数 hBaseData表示。
  3. 使用与用于计算由 hBaseData 参数表示的哈希值相同的哈希算法对步骤 1 的结果进行哈希处理。
  4. 使用与用于计算由 hBaseData 参数表示的哈希值相同的哈希算法对步骤 2 的结果进行哈希处理。
  5. 将步骤 3 的结果与步骤 4 的结果连接在一起。
  6. 使用步骤 5 结果的第一个 n 个 字节作为派生密钥。
默认 RSA 完全加密服务提供程序是MICROSOFT RSA 强加密提供程序。 默认 DSS 签名 Diffie-Hellman 加密服务提供程序是Microsoft增强型 DSS Diffie-Hellman 加密提供程序。 其中每个 CSP 对于 RC2 和 RC4,都有默认的 128 位对称密钥长度。

下表列出了按算法和提供程序列出的会话密钥的最小、默认值和最大密钥长度。

供应商 算法 最小密钥长度 默认密钥长度 最大密钥长度
MS Base RC4 和 RC2 40 40 56
MS Base DES 56 56 56
MS 增强 RC4 和 RC2 40 128 128
MS 增强 DES 56 56 56
MS 增强 3DES 112 112 112 112
MS 增强 3DES 168 168 168
MS Strong RC4 和 RC2 40 128 128
MS Strong DES 56 56 56
MS Strong 3DES 112 112 112 112
MS Strong 3DES 168 168 168
DSS/DH 基础 RC4 和 RC2 40 40 56
DSS/DH 基础 Cylink MEK 40 40 40
DSS/DH 基础 DES 56 56 56
DSS/DH Enh RC4 和 RC2 40 128 128
DSS/DH Enh Cylink MEK 40 40 40
DSS/DH Enh DES 56 56 56
DSS/DH Enh 3DES 112 112 112 112
DSS/DH Enh 3DES 168 168 168
 

例子

有关使用此函数的示例,请参阅 示例 C 程序:从密码派生会话密钥。

要求

要求 价值
最低支持的客户端 Windows XP [仅限桌面应用]
支持的最低服务器 Windows Server 2003 [仅限桌面应用]
目标平台 窗户
标头 wincrypt.h
Advapi32.lib
DLL Advapi32.dll

另请参阅

CryptAcquireContext

CryptCreateHash

CryptDestroyHash

CryptDestroyKey

CryptExportKey

CryptGenKey

CryptGetKeyParam

CryptHashData

CryptHashSessionKey

CryptSetKeyParam

密钥生成和 Exchange 函数