CryptDecrypt 函数 (wincrypt.h)

重要 此 API 已弃用。 新的和现有的软件应开始使用 加密下一代 API。 Microsoft 可能会在将来的版本中删除此 API。
 
CryptDecrypt 函数使用 CryptEncrypt 函数解密以前加密的数据。

对支持 安全/多用途 Internet 邮件扩展(S/MIME)电子邮件互操作性的重要更改已经对影响信封邮件处理的 CryptoAPI 进行了。 有关详细信息,请参阅 CryptMsgOpenToEncode的“备注”部分。

语法

BOOL CryptDecrypt(
  [in]      HCRYPTKEY  hKey,
  [in]      HCRYPTHASH hHash,
  [in]      BOOL       Final,
  [in]      DWORD      dwFlags,
  [in, out] BYTE       *pbData,
  [in, out] DWORD      *pdwDataLen
);

参数

[in] hKey

用于解密的密钥的句柄。 应用程序通过使用 CryptGenKeyCryptImportKey 函数获取此句柄。

此密钥指定要使用的解密算法。

[in] hHash

哈希对象的句柄。 如果要同时解密和哈希处理数据,则会在此参数中传递哈希对象的句柄。 哈希值使用解密的 纯文本进行更新。 当同时解密和验证签名时,此选项非常有用。

在调用 CryptDecrypt之前,应用程序必须通过调用 CryptCreateHash 函数来获取哈希对象的句柄。 解密完成后,可以使用 CryptGetHashParam 函数获取哈希值,也可以使用 CryptSignHash 函数对其进行签名,也可以使用 CryptVerifySignature 函数验证 数字签名

如果未执行任何哈希,则此参数必须为零。

[in] Final

一个布尔值,该值指定是否是正在解密的序列中的最后一节。 如果此值是最后一个或唯一块,则为 true。 如果这不是最后一个块,则此值 FALSE。 有关详细信息,请参阅“备注”。

[in] dwFlags

定义了以下标志值。

价值 意义
CRYPT_OAEP
0x00000040
使用最佳非对称加密填充 (OAEP) (PKCS #1 版本 2)。 此标志仅受具有 RSA 加密/解密功能的 Microsoft 增强加密提供程序 支持。 此标志不能与 CRYPT_DECRYPT_RSA_NO_PADDING_CHECK 标志组合在一起。
CRYPT_DECRYPT_RSA_NO_PADDING_CHECK
0x00000020
BLOB 上执行解密,而无需检查填充。 此标志仅受具有 RSA 加密/解密功能的 Microsoft 增强加密提供程序 支持。 此标志不能与 CRYPT_OAEP 标志结合使用。

[in, out] pbData

指向包含要解密的数据的缓冲区的指针。 执行解密后,纯文本将重新放置在同一缓冲区中。

此缓冲区中的加密字节数由 pdwDataLen指定。

[in, out] pdwDataLen

指向 DWORD 值的指针,该值指示 pbData 缓冲区的长度。 调用此函数之前,调用应用程序会将 DWORD 值设置为要解密的字节数。 返回后,DWORD 值包含解密的纯文本的字节数。

使用 块密码 时,此数据长度必须是块大小的倍数,除非这是要解密的数据的最后一部分,Final 参数 TRUE

返回值

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

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

NTE 前面带的错误代码由正在使用的特定 CSP 生成。 下面是一些可能的错误代码。

价值 描述
ERROR_INVALID_HANDLE
其中一个参数指定无效的句柄。
ERROR_INVALID_PARAMETER
其中一个参数包含无效的值。 这通常是无效的指针。
NTE_BAD_ALGID
hKey会话密钥 指定此 CSP 不支持的算法。
NTE_BAD_DATA
要解密的数据无效。 例如,使用块密码并且 最终 标志 FALSE时,由 pdwDataLen 指定的值必须是块大小的倍数。 当发现 填充 无效时,也可以返回此错误。
NTE_BAD_FLAGS
dwFlags 参数为非零。
NTE_BAD_HASH
hHash 参数包含无效的句柄。
NTE_BAD_KEY
hKey 参数不包含密钥的有效句柄。
NTE_BAD_LEN
输出缓冲区的大小太小,无法容纳生成的纯文本。
NTE_BAD_UID
找不到创建密钥时指定的 CSP 上下文。
NTE_DOUBLE_ENCRYPT
应用程序尝试解密同一数据两次。
NTE_FAIL
函数以某种意外的方式失败。

言论

如果要解密大量数据,可以通过重复调用 CryptDecrypt 在节中完成。 Final 参数必须仅在对 CryptDecrypt的最后一次调用上设置为 TRUE,以便解密引擎可以正确完成解密过程。 当 最终TRUE时,将执行以下额外操作:

  • 如果密钥是块密码键,则数据将填充到密码块大小的倍数。 若要查找密码的块大小,请使用 CryptGetKeyParam 获取密钥的KP_BLOCKLEN值。
  • 如果密码在 链接模式下运行,则下一个 CryptDecrypt 操作会将密码的反馈寄存器重置为密钥的KP_IV值。
  • 如果密码是流密码,则下一个 CryptDecrypt 调用会将密码重置为其初始 状态

无法将密码的反馈寄存器设置为键的KP_IV值,而无需将 Final 参数设置为 TRUE。 如果需要,就像不想添加其他填充块或更改每个块的大小一样,可以通过使用 CryptDuplicateKey 函数创建原始键的副本,并将重复键传递给 CryptDecrypt 函数来模拟此操作。 这会导致原始密钥的KP_IV放置在重复键中。 创建或导入原始密钥后,无法使用原始密钥进行加密,因为密钥的反馈寄存器将更改。 以下伪代码演示如何执行此操作。

// Set the IV for the original key. Do not use the original key for 
// encryption or decryption after doing this because the key's 
// feedback register will get modified and you cannot change it.
CryptSetKeyParam(hOriginalKey, KP_IV, newIV)

while(block = NextBlock())
{
    // Create a duplicate of the original key. This causes the 
    // original key's IV to be copied into the duplicate key's 
    // feedback register.
    hDuplicateKey = CryptDuplicateKey(hOriginalKey)

    // Decrypt the block with the duplicate key.
    CryptDecrypt(hDuplicateKey, block)

    // Destroy the duplicate key. Its feedback register has been 
    // modified by the CryptEncrypt function, so it cannot be used
    // again. It will be re-duplicated in the next iteration of the 
    // loop.
    CryptDestroyKey(hDuplicateKey)
}

Microsoft 增强型加密提供程序 支持使用 RSA 公钥进行直接加密,并使用 RSA 私钥进行解密。 加密使用 PKCS #1 填充。 在解密时,会验证此填充。 要解密的数据 密码文本 长度必须与用于解密数据的 RSA 密钥的模数相同。 如果密码文本在最重要的字节数中为零,则必须将这些字节包含在输入数据缓冲区和输入缓冲区长度中。 密码文本必须采用 little-endian 格式。

例子

有关使用此函数的示例,请参阅 示例 C 程序:解密文件

要求

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

另请参阅

CryptCreateHash

CryptEncrypt

CryptGenKey

CryptGetHashParam

CryptGetKeyParam

CryptImportKey

CryptMsgOpenToEncode

CryptSignHash

CryptVerifySignature

数据加密/解密函数