CryptSignHashA 函数 (wincrypt.h)

重要 此 API 已弃用。 新的和现有的软件应开始使用 加密下一代 API。 Microsoft 可能会在将来的版本中删除此 API。
 
CryptSignHash 函数对数据进行签名。 由于所有签名算法都是非对称的,因此速度缓慢,因此 CryptoAPI 不允许直接对数据进行签名。 相反,首先对数据 进行哈希处理,并使用 CryptSignHash 对哈希进行签名。

语法

BOOL CryptSignHashA(
  [in]      HCRYPTHASH hHash,
  [in]      DWORD      dwKeySpec,
  [in]      LPCSTR     szDescription,
  [in]      DWORD      dwFlags,
  [out]     BYTE       *pbSignature,
  [in, out] DWORD      *pdwSigLen
);

参数

[in] hHash

要签名的 哈希对象的 句柄。

[in] dwKeySpec

标识要从提供程序的容器使用的私钥。 它可以AT_KEYEXCHANGE或AT_SIGNATURE。

最初创建密钥对时会指定使用的签名算法。

Microsoft 基本加密提供程序支持的唯一签名算法是 RSA 公钥算法。

[in] szDescription

此参数不再使用,必须设置为 NULL 以防止安全漏洞。 但是,在 Microsoft 基本加密提供程序中仍支持它实现向后兼容性。

[in] dwFlags

定义了以下标志值。

含义
CRYPT_NOHASHOID
0x00000001
与 RSA 提供程序一起使用。 OID) (哈希 对象标识符 未放置在 RSA 公钥加密中。 如果未设置此标志,则默认签名中的哈希 OID 将按照 PKCS #1 中 DigestInfo 的定义指定。
CRYPT_TYPE2_FORMAT
0x00000002
未使用此标志。
CRYPT_X931_FORMAT
0x00000004
使用 ANSI X9.31 标准中指定的 RSA 签名填充方法。

[out] pbSignature

指向接收签名数据的缓冲区的指针。

此参数可以为 NULL ,用于设置缓冲区大小以用于内存分配。 有关详细信息,请参阅 检索长度未知的数据

[in, out] pdwSigLen

指向 DWORD 值的指针,该值指定 pbSignature 缓冲区的大小(以字节为单位)。 函数返回时, DWORD 值包含缓冲区中存储的字节数。

注意 处理缓冲区中返回的数据时,应用程序必须使用返回的数据的实际大小。 实际大小可以略小于输入时指定的缓冲区的大小。 (输入时,缓冲区大小通常指定得足够大,以确保最大的输出数据适合 buffer。) 输出时,此参数指向的变量将更新,以反映复制到缓冲区的数据的实际大小。
 

返回值

如果该函数成功,则函数返回 TRUE

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

“NTE”开头的错误代码由你使用的特定 CSP 生成。 一些可能的错误代码随之而来。

返回代码 说明
ERROR_INVALID_HANDLE
其中一个参数指定无效的句柄。
ERROR_INVALID_PARAMETER
其中一个参数包含无效的值。 这通常是无效的指针。
ERROR_MORE_DATA
pbSignature 参数指定的缓冲区不够大,无法容纳返回的数据。 所需的缓冲区大小(以字节为单位)位于 pdwSigLenDWORD 值中。
NTE_BAD_ALGID
hHash 句柄指定此 CSP 不支持的算法,或者 dwKeySpec 参数具有不正确的值。
NTE_BAD_FLAGS
dwFlags 参数为非零。
NTE_BAD_HASH
hHash 参数指定的哈希对象无效。
NTE_BAD_UID
找不到创建哈希对象时指定的 CSP 上下文。
NTE_NO_KEY
dwKeySpec 指定的私钥不存在。
NTE_NO_MEMORY
CSP 在操作期间内存不足。

注解

在调用此函数之前,必须调用 CryptCreateHash 函数以获取哈希对象的句柄。 然后使用 CryptHashDataCryptHashSessionKey 函数将数据或会话键添加到哈希对象。 CryptSignHash 函数完成哈希。

虽然 DSS CSP 支持使用 MD5 和 SHA 哈希算法进行哈希处理,但 DSS CSP 仅支持对 SHA 哈希进行签名。

调用此函数后,无法向哈希添加更多数据。 对 CryptHashDataCryptHashSessionKey 的其他调用失败。

应用程序使用完哈希后,通过调用 CryptDestroyHash 函数来销毁哈希对象。

默认情况下,Microsoft RSA 提供程序对签名使用 PKCS #1 填充方法。 签名的 DigestInfo 元素中的哈希 OID 会自动设置为与哈希对象关联的算法 OID。 使用 CRYPT_NOHASHOID 标志会导致签名中省略此 OID。

有时,必须在其他位置生成的哈希值进行签名。 这可以通过使用以下操作序列来完成:

  1. 使用 CryptCreateHash 创建哈希对象。
  2. 使用 CryptSetHashParamdwParam 参数的 HP_HASHVAL 值设置哈希对象中的哈希值。
  3. 使用 CryptSignHash 对哈希值进行签名,并获取数字签名块。
  4. 使用 CryptDestroyHash 销毁哈希对象。

示例

以下示例演示通过先对要签名的数据进行哈希处理,然后使用 CryptSignHash 函数对哈希进行签名来对数据进行签名。

//-------------------------------------------------------------
// Declare and initialize variables.

HCRYPTPROV hProv;
BYTE *pbBuffer= (BYTE *)"Sample data that is to be signed.";
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
HCRYPTHASH hHash;

//--------------------------------------------------------------------
// This code assumes that a cryptographic context handle, hProv,
// and a hash handle, hHash, are available.
// For code needed to acquire the context, see "Example C Program: 
// Signing a Hash and Verifying the Hash Signature."

//--------------------------------------------------------------------
// Compute the cryptographic hash of the buffer.

if(CryptHashData(
   hHash, 
   pbBuffer, 
   dwBufferLen, 
   0)) 
{
     printf("The data buffer has been hashed.\n");
}
else
{
     printf("Error during CryptHashData.\n");
     exit(1);
}
//--------------------------------------------------------------------
// Determine the size of the signature and allocate memory.

dwSigLen= 0;
if(CryptSignHash(
   hHash, 
   AT_SIGNATURE, 
   szDescription, 
   0, 
   NULL, 
   &dwSigLen)) 
{
     printf("Signature length %d found.\n",dwSigLen);
}
else
{
     printf("Error during CryptSignHash\n");
     exit(1);
}
//--------------------------------------------------------------------
// Allocate memory for the signature buffer.

if(pbSignature = (BYTE *)malloc(dwSigLen))
{
     printf("Memory allocated for the signature.\n");
}
else
{
     printf("Out of memory\n");
     exit(1);
}
//--------------------------------------------------------------------
// Sign the hash object.

if(CryptSignHash(
   hHash, 
   AT_SIGNATURE, 
   szDescription, 
   0, 
   pbSignature, 
   &dwSigLen)) 
{
     printf("pbSignature is the hash signature.\n");
}
else
{
     printf("Error during CryptSignHash.\n");
     exit(1);
}
//--------------------------------------------------------------------
// Destroy the hash object.

if(hHash) 
  CryptDestroyHash(hHash);

有关包含此代码上下文的完整示例,请参阅 示例 C 程序:对哈希进行签名和验证哈希签名

注意

wincrypt.h 标头将 CryptSignHash 定义为别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将非特定编码别名的使用与非非特定编码的代码混合使用可能会导致不匹配,从而导致编译或运行时错误。 有关详细信息,请参阅 函数原型的约定

要求

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

另请参阅

CryptCreateHash

CryptDestroyHash

CryptHashData

CryptHashSessionKey

CryptVerifySignature

哈希和数字签名函数