CryptGenKey 函数 (wincrypt.h)

重要 此 API 已弃用。 新的和现有的软件应开始使用 加密下一代 API。 Microsoft 可能会在将来的版本中删除此 API。
 
CryptGenKey 函数生成随机加密密钥会话密钥公钥/私钥对在 phKey 中返回密钥或密钥对的句柄。 然后,可以根据需要将此句柄用于任何需要密钥句柄的 CryptoAPI 函数。

调用此函数时,调用应用程序必须指定算法。 由于此算法类型与密钥保持捆绑,因此以后执行实际加密操作时,应用程序无需指定该算法。

语法

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,请使用以下值之一。

含义
CALG_DH_EPHEM
指定“临时”Diffie-Hellman 键。
CALG_DH_SF
指定“存储并转发”Diffie-Hellman 密钥。
 

除了为 对称算法生成会话密钥外,此函数还可以生成 公钥/私钥对。 每个 CryptoAPI 客户端通常具有两个公钥/私钥对。 若要生成其中一个键对,请将 Algid 参数设置为以下值之一。

含义
AT_KEYEXCHANGE
密钥交换
AT_SIGNATURE
数字签名
 
注意 指定密钥规范AT_KEYEXCHANGE和AT_SIGNATURE时,用于生成密钥的算法标识符取决于所使用的提供程序。 因此,对于这些密钥规范,当指定 KP_ALGID 参数时,从 CryptGetKeyParam 返回的值 () 取决于使用的提供程序。 若要确定不同提供程序用于密钥规格AT_KEYEXCHANGE和AT_SIGNATURE的算法标识符,请参阅 ALG_ID
 

[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 位可以是零,也可以是以下一个或多个值的组合。

含义
CRYPT_ARCHIVABLE
如果设置了此标志,则可以导出密钥,直到通过调用 CryptDestroyKey 关闭其句柄。 这允许在创建时导出新生成的密钥,以便进行存档或密钥恢复。 关闭句柄后,该密钥不再可导出。
CRYPT_CREATE_IV
未使用此标志。
CRYPT_CREATE_SALT
如果设置了此标志,则会自动为密钥分配一个随机 盐值 。 可以使用 CryptGetKeyParam 函数检索此 salt 值,并将 dwParam 参数设置为 KP_SALT。

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

当通过 CryptExportKey) (导出具有非零盐值的键时,还必须获取 盐值 并将其与 密钥 BLOB 一起保留。

CRYPT_DATA_KEY
未使用此标志。
CRYPT_EXPORTABLE
如果设置了此标志,则可以使用 CryptExportKey 函数将密钥从 CSP 传输到密钥 BLOB 中。 由于会话密钥通常必须可导出,因此通常应在创建时设置此标志。

如果未设置此标志,则无法导出密钥。 对于会话密钥,这意味着该密钥仅在当前会话中可用,并且只有创建该密钥的应用程序才能使用它。 对于 公钥/私钥对,这意味着无法传输或备份私钥。

此标志仅适用于会话密钥和 私钥 BLOB。 它不适用于始终可导出的公钥。

CRYPT_FORCE_KEY_PROTECTION_HIGH
此标志指定强密钥保护。 设置此标志后,系统会提示用户在创建密钥时输入密钥的密码。 每当使用此密钥时,系统会提示用户输入密码。

此标志仅由 Microsoft 提供的 CSP 使用。 第三方 CSP 将定义自己的行为来提供强大的密钥保护。

在系统注册表中指定强键保护时,指定此标志会导致与使用 CRYPT_USER_PROTECTED 标志调用此函数的结果相同。

如果指定了此标志,并且 hProv 参数中的提供程序句柄是使用 CRYPT_VERIFYCONTEXTCRYPT_SILENT 标志创建的,则此函数会将最后一个错误设置为 NTE_SILENT_CONTEXT 并返回零。

Windows Server 2003 和 Windows XP: 不支持此标志。

CRYPT_KEK
未使用此标志。
CRYPT_INITIATOR
未使用此标志。
CRYPT_NO_SALT
此标志指定为 40 位对称密钥分配无盐值。 有关详细信息,请参阅 Salt 值功能
CRYPT_ONLINE
未使用此标志。
CRYPT_PREGEN
此标志指定初始 Diffie-Hellman 或 DSS 密钥生成。 此标志仅适用于 Diffie-Hellman 和 DSS CSP。 使用时,将使用默认密钥长度,除非 在 dwFlags 参数的上限 16 位中指定了密钥长度。 如果使用 CryptSetKeyParam 在 PREGEN Diffie-Hellman 或 DSS 密钥上设置涉及密钥长度的参数,则密钥长度必须与此处设置的密钥长度兼容。
CRYPT_RECIPIENT
未使用此标志。
CRYPT_SF
未使用此标志。
CRYPT_SGCKEY
未使用此标志。
CRYPT_USER_PROTECTED
如果设置了此标志,当某些操作尝试使用此密钥时,将通过对话框或其他方法通知用户。 精确行为由正在使用的 CSP 指定。 如果提供程序上下文是使用 CRYPT_SILENT 标志集打开的,则使用此标志会导致失败,并且最后一个错误设置为 NTE_SILENT_CONTEXT。
CRYPT_VOLATILE
未使用此标志。

[out] phKey

函数将新生成的密钥的句柄复制到的地址。 使用完密钥后,通过调用 CryptDestroyKey 函数删除密钥的句柄。

返回值

如果成功,则返回非零值,否则返回零。

有关扩展的错误信息,请调用 GetLastError

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

返回代码 说明
ERROR_INVALID_HANDLE
其中一个参数指定无效的句柄。
ERROR_INVALID_PARAMETER
其中一个参数包含无效的值。 这通常是无效的指针。
NTE_BAD_ALGID
Algid 参数指定此 CSP 不支持的算法。
NTE_BAD_FLAGS
dwFlags 参数包含无效的值。
NTE_BAD_UID
hProv 参数不包含有效的上下文句柄。
NTE_FAIL
函数以某种意外方式失败。
NTE_SILENT_CONTEXT
提供程序无法执行该操作,因为上下文是以无提示方式获取的。

注解

如果为 对称块密码生成密钥,则默认情况下,密钥在 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

另请参阅

CryptAcquireContext

CryptDestroyKey

CryptExportKey

CryptGetKeyParam

CryptImportKey

CryptSetKeyParam

密钥生成和交换函数

加密服务提供程序的线程处理问题