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 值包含缓冲区中存储的字节数。

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

返回值

如果函数成功,该函数将返回 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. 通过使用 CryptSetHashParam中的 dwParam 参数 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 [仅限桌面应用]
目标平台 窗户
标头 wincrypt.h
Advapi32.lib
DLL Advapi32.dll

另请参阅

CryptCreateHash

CryptDestroyHash

CryptHashData

CryptHashSessionKey

CryptVerifySignature

哈希和数字签名函数