CryptDeriveKey 函数 (wincrypt.h)
此函数与 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。
有关与 Microsoft 基本加密提供程序一起使用 ALG_ID 值的详细信息,请参阅 基本提供程序算法。 有关 ALG_ID 值与 Microsoft Strong Cryptographic Provider 或 Microsoft Enhanced Cryptographic Provider 一起使用的详细信息,请参阅 增强的提供程序算法。
[in] hBaseData
已馈送精确基础数据的 哈希对象的 句柄。
若要获取此句柄,应用程序必须先使用 CryptCreateHash 创建哈希对象,然后使用 CryptHashData 将基本数据添加到哈希对象。 哈希和数字签名中详细介绍了此过程。
[in] dwFlags
指定生成的密钥的类型。
生成密钥时,可以设置会话密钥的大小。 密钥大小(表示密钥取模的长度(以位为单位)是使用此参数的 16 位设置的。 因此,如果要生成 128 位 RC4 会话密钥,则0x00800000值与任何其他 dwFlags 预定义值组合使用按位 OR 运算。 由于更改了导出控制限制,默认 CSP 和默认 密钥长度 可能会在操作系统版本之间更改。 加密和解密都使用相同的 CSP,并且使用 dwFlags 参数显式设置密钥长度,以确保不同操作系统平台上的互操作性,这一点很重要。
此参数的低 16 位可以为零,或者可以使用按位 OR 运算符来指定以下一个或多个标志。
值 | 含义 |
---|---|
|
通常,从 哈希 值生成会话键时,存在大量剩余位。 例如,如果哈希值为 128 位,会话密钥为 40 位,则剩余 88 位。
如果设置了此标志,则会根据未使用的哈希值位为键分配 一个 salt 值。 可以使用 CryptGetKeyParam 函数检索此 salt 值,并将 dwParam 参数设置为 KP_SALT。 如果未设置此标志,则会为键指定一个 salt 值零。 当使用 CryptExportKey) 将具有非零 salt 值的键导出 (时,还必须获取 salt 值并将其与 密钥 BLOB 一起保存。 |
|
如果设置了此标志,则会话密钥可以通过 CryptExportKey 函数从 CSP 传输到密钥 BLOB 中。 由于键通常必须可导出,因此通常应设置此标志。
如果未设置此标志,则会话密钥不可导出。 这意味着密钥仅在当前会话中可用,并且只有创建它的应用程序才能使用它。 此标志不适用于 公钥/私钥对。 |
|
此标志指定为 40 位对称密钥分配无盐值。 有关详细信息,请参阅 Salt 值功能。 |
|
某些 CSP 使用从多个哈希值派生的会话密钥。 在这种情况下,必须多次调用 CryptDeriveKey 。
如果设置了此标志,则不会生成新的会话密钥。 相反,会修改 phKey 指定的密钥。 此标志的精确行为取决于所生成的密钥类型和使用的特定 CSP。 Microsoft 加密服务提供程序忽略此标志。 |
|
此标志仅用于 Schannel 提供程序。 如果设置了此标志,则要生成的密钥是服务器写入密钥;否则,它是客户端写入密钥。 |
[in, out] phKey
指向 HCRYPTKEY 变量的指针,用于接收新生成的密钥的句柄的地址。 使用完密钥后,通过调用 CryptDestroyKey 函数释放句柄。
返回值
如果函数成功,则函数) 返回非零 (TRUE 。
如果函数失败,它将返回零 (FALSE) 。 有关扩展的错误信息,请调用 GetLastError。
以“NTE”开头的错误代码由使用的特定 CSP 生成。 下表列出了一些可能的错误代码。
返回代码 | 说明 |
---|---|
|
其中一个参数指定无效的句柄。 |
|
其中一个参数包含无效的值。 这通常是无效的指针。 |
|
Algid 参数指定此 CSP 不支持的算法。 |
|
dwFlags 参数包含无效的值。 |
|
hBaseData 参数不包含哈希对象的有效句柄。 |
|
尝试将数据添加到已标记为“已完成”的哈希对象。 |
|
hProv 参数不包含有效的上下文句柄。 |
|
函数以某种意外的方式失败。 |
|
提供程序无法执行该操作,因为上下文是以无提示方式获取的。 |
注解
为 对称块加密生成密钥时,默认情况下,密钥在加密 块链 (CBC) 模式下设置,初始化向量为零。 此 密码模式 为批量加密数据提供了良好的默认方法。 若要更改这些参数,请使用 CryptSetKeyParam 函数。
CryptDeriveKey 函数完成哈希。 调用 CryptDeriveKey 后,无法向哈希添加更多数据。 对 CryptHashData 或 CryptHashSessionKey 的其他调用失败。 使用哈希完成应用程序后,必须调用 CryptDestroyHash 来销毁哈希对象。
若要选择适当的 密钥长度,建议使用以下方法。
- 若要枚举 CSP 支持的算法并获取每个算法的最大和最小密钥长度,请使用 PP_ENUMALGS_EX 调用 CryptGetProvParam 。
- 使用最小和最大长度选择适当的密钥长度。 并不总是建议选择最大长度,因为这可能会导致性能问题。
- 选择所需的密钥长度后,请使用 dwFlags 参数的上限 16 位来指定密钥长度。
- 通过重复常量 0x36 64 次,形成 64 字节缓冲区。 让 k 是输入参数 hBaseData 表示的哈希值的长度。 使用输入参数 hBaseData 表示的哈希值,将缓冲区的前k 个字节设置为 XOR 操作的结果。
- 通过重复常量 0x5C 64 次,形成 64 字节缓冲区。 使用输入参数 hBaseData 表示的哈希值,将缓冲区的前k 个字节设置为 XOR 操作的结果。
- 使用与用于计算 hBaseData 参数表示的哈希值的相同哈希算法,对步骤 1 的结果进行哈希处理。
- 使用与用于计算 hBaseData 参数表示的哈希值的相同哈希算法,对步骤 2 的结果进行哈希处理。
- 将步骤 3 的结果与步骤 4 的结果连接在一起。
- 使用步骤 5 的结果的前 n 个字节作为派生键。
下表按算法和提供程序列出了会话密钥的最小、默认和最大密钥长度。
提供程序 | 算法 | 最小密钥长度 | 默认密钥长度 | 最大密钥长度 |
---|---|---|---|---|
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 [仅限桌面应用] |
目标平台 | Windows |
标头 | wincrypt.h |
Library | Advapi32.lib |
DLL | Advapi32.dll |
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈