CryptGenKey 函数 (wincrypt.h)
调用此函数时,调用应用程序必须指定算法。 由于此算法类型与密钥保持捆绑,因此以后执行实际加密操作时,应用程序无需指定该算法。
语法
BOOL CryptGenKey(
[in] HCRYPTPROV hProv,
[in] ALG_ID Algid,
[in] DWORD dwFlags,
[out] HCRYPTKEY *phKey
);
参数
[in] hProv
加密服务提供程序的句柄 (CSP) 调用 CryptAcquireContext 创建的。
[in] Algid
一个ALG_ID值,该值标识要为其生成密钥的算法。 此参数的值因使用的 CSP 而异。
有关要与 Microsoft 基本加密提供程序一起使用 的ALG_ID 值,请参阅 基本提供程序算法。
有关 要 与 Microsoft 强加密提供程序或 Microsoft 增强型加密提供程序一起使用的ALG_ID值,请参阅 增强的提供程序算法。
对于 Diffie-Hellman CSP,请使用以下值之一。
值 | 含义 |
---|---|
|
指定“临时”Diffie-Hellman 键。 |
|
指定“存储并转发”Diffie-Hellman 密钥。 |
除了为 对称算法生成会话密钥外,此函数还可以生成 公钥/私钥对。 每个 CryptoAPI 客户端通常具有两个公钥/私钥对。 若要生成其中一个键对,请将 Algid 参数设置为以下值之一。
值 | 含义 |
---|---|
|
密钥交换 |
|
数字签名 |
[in] dwFlags
指定生成的密钥的类型。 生成密钥时,可以设置会话密钥、RSA 签名密钥和 RSA 密钥 交换 密钥的大小。 密钥大小(以位为单位)表示密钥模数的长度,是使用此参数的上 16 位设置的。 因此,如果要生成 2,048 位 RSA 签名密钥,则 0x08000000 值与任何其他 dwFlags 预定义值组合使用按位 OR 运算。 0x08000000的上限 16 位是0x0800位,即十进制 2,048。 RSA1024BIT_KEY值可用于指定 1024 位 RSA 密钥。
由于更改导出控制限制,默认 CSP 和默认 密钥长度 可能会在操作系统版本之间更改。 重要的是,加密和解密使用相同的 CSP,并且使用 dwFlags 参数显式设置密钥长度,以确保在不同操作系统平台上的互操作性。
具体而言,默认 RSA 完整加密服务提供程序是 Microsoft RSA 强加密提供程序。 默认的 DSS 签名 Diffie-Hellman 加密服务提供程序是 Microsoft 增强型 DSS Diffie-Hellman 加密提供程序。 对于 RC2 和 RC4,其中每个 CSP 的默认对称密钥长度为 128 位,公钥算法的默认密钥长度为 1,024 位。
如果上限 16 位为零,则生成默认密钥大小。 如果指定了大于最大值或小于最小值的键,则调用将失败并显示ERROR_INVALID_PARAMETER代码。
下表列出了从 Windows XP 开始的最小、默认和最大签名和交换密钥长度。
密钥类型和提供程序 | 最小长度 | 默认长度 | 最大长度。 |
---|---|---|---|
RSA 基本提供程序 签名和 ExchangeKeys |
384 | 512 | 16,384 |
RSA 强提供程序和增强型提供程序 签名和交换密钥 |
384 | 1,024 | 16,384 |
DSS 基本提供程序 签名密钥 |
512 | 1,024 | 1,024 |
DSS 基本提供程序 交换密钥 |
不适用 | 不适用 | 不适用 |
DSS/DH 基本提供程序 签名密钥 |
512 | 1,024 | 1,024 |
DSS/DH 基本提供程序 交换密钥 |
512 | 512 | 1,024 |
DSS/DH 增强型提供程序 签名密钥 |
512 | 1,024 | 1,024 |
DSS/DH 增强型提供程序 交换密钥 |
512 | 1,024 | 4,096 |
有关会话密钥长度,请参阅 CryptDeriveKey。
有关使用 Microsoft 提供程序生成的密钥的详细信息,请参阅 Microsoft 加密服务提供程序。
此参数的较低 16 位可以是零,也可以是以下一个或多个值的组合。
值 | 含义 |
---|---|
|
如果设置了此标志,则可以导出密钥,直到通过调用 CryptDestroyKey 关闭其句柄。 这允许在创建时导出新生成的密钥,以便进行存档或密钥恢复。 关闭句柄后,该密钥不再可导出。 |
|
未使用此标志。 |
|
如果设置了此标志,则会自动为密钥分配一个随机 盐值 。 可以使用 CryptGetKeyParam 函数检索此 salt 值,并将 dwParam 参数设置为 KP_SALT。
如果未设置此标志,则为键提供零的盐值。 当通过 CryptExportKey) (导出具有非零盐值的键时,还必须获取 盐值 并将其与 密钥 BLOB 一起保留。 |
|
未使用此标志。 |
|
如果设置了此标志,则可以使用 CryptExportKey 函数将密钥从 CSP 传输到密钥 BLOB 中。 由于会话密钥通常必须可导出,因此通常应在创建时设置此标志。
如果未设置此标志,则无法导出密钥。 对于会话密钥,这意味着该密钥仅在当前会话中可用,并且只有创建该密钥的应用程序才能使用它。 对于 公钥/私钥对,这意味着无法传输或备份私钥。 此标志仅适用于会话密钥和 私钥 BLOB。 它不适用于始终可导出的公钥。 |
|
此标志指定强密钥保护。 设置此标志后,系统会提示用户在创建密钥时输入密钥的密码。 每当使用此密钥时,系统会提示用户输入密码。
此标志仅由 Microsoft 提供的 CSP 使用。 第三方 CSP 将定义自己的行为来提供强大的密钥保护。 在系统注册表中指定强键保护时,指定此标志会导致与使用 CRYPT_USER_PROTECTED 标志调用此函数的结果相同。 如果指定了此标志,并且 hProv 参数中的提供程序句柄是使用 CRYPT_VERIFYCONTEXT 或 CRYPT_SILENT 标志创建的,则此函数会将最后一个错误设置为 NTE_SILENT_CONTEXT 并返回零。 Windows Server 2003 和 Windows XP: 不支持此标志。 |
|
未使用此标志。 |
|
未使用此标志。 |
|
此标志指定为 40 位对称密钥分配无盐值。 有关详细信息,请参阅 Salt 值功能。 |
|
未使用此标志。 |
|
此标志指定初始 Diffie-Hellman 或 DSS 密钥生成。 此标志仅适用于 Diffie-Hellman 和 DSS CSP。 使用时,将使用默认密钥长度,除非 在 dwFlags 参数的上限 16 位中指定了密钥长度。 如果使用 CryptSetKeyParam 在 PREGEN Diffie-Hellman 或 DSS 密钥上设置涉及密钥长度的参数,则密钥长度必须与此处设置的密钥长度兼容。 |
|
未使用此标志。 |
|
未使用此标志。 |
|
未使用此标志。 |
|
如果设置了此标志,当某些操作尝试使用此密钥时,将通过对话框或其他方法通知用户。 精确行为由正在使用的 CSP 指定。 如果提供程序上下文是使用 CRYPT_SILENT 标志集打开的,则使用此标志会导致失败,并且最后一个错误设置为 NTE_SILENT_CONTEXT。 |
|
未使用此标志。 |
[out] phKey
函数将新生成的密钥的句柄复制到的地址。 使用完密钥后,通过调用 CryptDestroyKey 函数删除密钥的句柄。
返回值
如果成功,则返回非零值,否则返回零。
有关扩展的错误信息,请调用 GetLastError。
“NTE”开头的错误代码由使用的特定 CSP 生成。 下表列出了一些可能的错误代码。
返回代码 | 说明 |
---|---|
|
其中一个参数指定无效的句柄。 |
|
其中一个参数包含无效的值。 这通常是无效的指针。 |
|
Algid 参数指定此 CSP 不支持的算法。 |
|
dwFlags 参数包含无效的值。 |
|
hProv 参数不包含有效的上下文句柄。 |
|
函数以某种意外方式失败。 |
|
提供程序无法执行该操作,因为上下文是以无提示方式获取的。 |
注解
如果为 对称块密码生成密钥,则默认情况下,密钥在 CBC) 模式下设置 密码块链接 (初始化向量为零。 此 密码模式 为批量加密数据提供了良好的默认方法。 若要更改这些参数,请使用 CryptSetKeyParam 函数。
若要选择适当的 密钥长度,建议使用以下方法:
- 枚举 CSP 支持的算法,并获取每个算法的最大和最小密钥长度。 为此,请使用 PP_ENUMALGS_EX 调用 CryptGetProvParam 。
- 使用最小和最大长度选择适当的密钥长度。 并不总是建议选择最大长度,因为这可能会导致性能问题。
- 选择所需的密钥长度后,请使用 dwFlags 参数的上限 16 位来指定密钥长度。
示例
以下示例演示如何创建随机会话密钥。 有关包含此示例的完整上下文的示例,请参阅 示例 C 程序:加密文件。 有关使用此函数的另一个示例,请参阅 示例 C 程序:解密文件。
//-------------------------------------------------------------------
// Declare the handle to the key.
HCRYPTKEY hKey;
//-------------------------------------------------------------------
// This example assumes that a cryptographic context
// has been acquired, and that it is stored in hCryptProv.
//---------------------------------------------------------------
// Create a random session key.
if(CryptGenKey(
hCryptProv,
ENCRYPT_ALGORITHM,
KEYLENGTH | CRYPT_EXPORTABLE,
&hKey))
{
printf("A session key has been created.\n");
}
else
{
printf("Error during CryptGenKey.\n");
exit(1);
}
//-------------------------------------------------------------------
// The key created can be exported into a key BLOB that can be
// written to a file.
// ...
// When you have finished using the key, free the resource.
if (!CryptDestroyKey(hKey))
{
printf("Error during CryptDestroyKey.\n");
exit(1);
}
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows XP [仅限桌面应用] |
最低受支持的服务器 | Windows Server 2003 [仅限桌面应用] |
目标平台 | Windows |
标头 | wincrypt.h |
Library | Advapi32.lib |
DLL | Advapi32.dll |
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈