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

调用 CryptAcquireContext创建的 加密服务提供商 (CSP)的句柄。

[in] Algid

一个 ALG_ID 值,该值标识要为其生成密钥的算法。 此参数的值因使用的 CSP 而异。

有关 ALG_ID 值与 Microsoft 基本加密提供程序一起使用,请参阅 基提供程序算法

若要 ALG_ID 值与Microsoft强加密提供程序或Microsoft增强加密提供程序一起使用,请参阅 增强提供程序算法

对于 Diffie-Hellman CSP,请使用以下值之一。

价值 意义
CALG_DH_EPHEM
指定“临时”Diffie-Hellman 键。
CALG_DH_SF
指定“存储和转发”Diffie-Hellman 键。
 

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

价值 意义
AT_KEYEXCHANGE
密钥交换
AT_SIGNATURE
数字签名
 
注意 指定密钥规范AT_KEYEXCHANGE和AT_SIGNATURE时,用于生成密钥的算法标识符取决于使用的提供程序。 因此,对于这些密钥规范,从 CryptGetKeyParam 返回的值(指定KP_ALGID参数时)取决于使用的提供程序。 若要确定不同提供程序对密钥规格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 加密提供程序。 其中每个 CSP 都有 RC2 和 RC4 的默认 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 基本提供程序

Exchange 密钥

不適用 不適用 不適用
DSS/DH 基本提供程序

签名密钥

512 1,024 1,024
DSS/DH 基本提供程序

Exchange 密钥

512 512 1,024
DSS/DH 增强型提供程序

签名密钥

512 1,024 1,024
DSS/DH 增强型提供程序

Exchange 密钥

512 1,024 4,096
 

有关会话密钥长度,请参阅 CryptDeriveKey

有关使用Microsoft提供程序生成的密钥的详细信息,请参阅 Microsoft 加密服务提供程序

此参数的低 16 位可以是零位,也可以是以下一个或多个值的组合。

价值 意义
CRYPT_ARCHIVABLE
如果设置了此标志,则可以导出密钥,直到调用 CryptDestroyKey关闭其句柄。 这允许在创建时导出新生成的密钥,以便进行存档或密钥恢复。 关闭句柄后,该键将不再可导出。
CRYPT_CREATE_IV
不使用此标志。
CRYPT_CREATE_SALT
如果设置了此标志,则会自动为密钥分配随机 盐值。 可以通过将 CryptGetKeyParam 函数与 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
此标志指定为四十位 对称密钥分配无 值。 有关详细信息,请参阅 Salt Value 功能
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 [仅限桌面应用]
目标平台 窗户
标头 wincrypt.h
Advapi32.lib
DLL Advapi32.dll

另请参阅

CryptAcquireContext

CryptDestroyKey

CryptExportKey

CryptGetKeyParam

CryptImportKey

CryptSetKeyParam

密钥生成和 Exchange 函数

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