[New - Windows NT]
[New - Windows 95, OEM Service Release 2]
CryptSignHash功能用于签署一条数据。因为所有的签名算法都是不对称的,因此非常慢,CryptoAPI不会直接对数据进行签名。相反,您必须先对数据进行散列,然后使用CryptSignHash对哈希值进行签名。
BOOL CRYPTFUNC CryptSignHash(
HCRYPTHASH【马】, | |
DWORD【dwKeySpec】, | |
LPCTSTR【sDescription】, | |
DWORD【dwFlags中】, | |
BYTE *【pbSignature】, | |
DWORD *【pdwSigLen】 | |
); |
参数
【马】
[in]要签名的哈希对象的句柄。
【dwKeySpec】
[in]用于签署哈希的密钥对。可以指定以下键:
* AT_KEYEXCHANGE __ Exchange私钥
* AT_SIGNATURE __签名私钥
当最初创建密钥对时,指定使用的签名算法。
Microsoft RSA Base Provider支持的唯一签名算法是RSA公钥算法。
【sDescription】
[in]描述要签署的数据的字符串。在生成签名之前,将此描述文本添加到散列对象。每当签名被认证(使用CryptVerifySignature)时,必须提供完全相同的描述字符串。这样可以确保签名者和验证者同意所签署或认证的内容。
一些CSP(而不是Microsoft RSA Base Provider)将向用户显示此描述字符串。这可以让用户确认他或她正在签署什么。这样可以保护用户免受不必要的应用,也可以减少误解。
如果签名中没有包含描述字符串,则此参数可以为NULL。通常,仅当使用不依赖于用户的签名密钥执行签名时才是这种情况。例如,当使用密钥交换私钥作为密钥交换协议的一部分执行签名操作时,通常不指定描述字符串。
【dwFlags中】
[in]标志值。此参数保留供将来使用,并且应始终为零。
【pbSignature】
[out]函数放置签名数据的缓冲区。
如果您正在做的是确定返回的签名数据所需的字节数,则此参数可以为NULL。
【pdwSigLen】
[in/out]签名数据长度的地址。在调用此函数之前,调用者应将此参数设置为【pbSignature】缓冲区的长度(以字节为单位)。返回时,该地址将包含签名数据中的字节数。
如果【pbSignature】指定的缓冲区不足以容纳数据,则该函数返回ERROR_MORE_DATA错误代码(通过GetLastError),并将所需的缓冲区大小(以字节为单位)存储到【pdwSigLen】指向的变量中。
如果【pbSignature】为NULL,则不会返回任何错误,并且函数将以【pdwSigLen】指向的变量存储数据的大小(以字节为单位)。
备注
在调用此函数之前,必须调用CryptCreateHash函数来获取哈希对象的句柄。然后使用CryptHashData或CryptHashSessionKey函数将数据或会话密钥添加到散列对象。
一旦这个功能完成,可以使用【马】句柄调用的唯一的哈希函数是CryptDestroyHash函数。
返回值
如果函数成功,返回值不为零。
如果函数失败,返回值为零。要检索扩展错误信息,请使用GetLastError功能。
下表列出了GetLastError函数最常返回的错误代码。由“NTE”开头的错误代码由您使用的特定CSP生成。
错误 | 描述 |
ERROR_INVALID_HANDLE | 其中一个参数指定一个无效句柄。 |
ERROR_INVALID_PARAMETER | 其中一个参数包含无效值。这通常是一个非法的指针。 |
NTE_BAD_ALGID | 【马】句柄指定此CSP不支持的算法。 |
NTE_BAD_FLAGS | 【dwFlags中】参数不为零。 |
NTE_BAD_HASH | 由【马】参数指定的散列对象无效。 |
NTE_BAD_UID | 创建哈希对象时指定的CSP上下文无法找到。 |
NTE_NO_KEY | 【dwKeySpec】指定的私钥不存在。 |
NTE_NO_MEMORY | CSP在运行过程中耗尽了内存。 |
例
#include < wincrypt.h >
HCRYPTPROV hProv = 0;
#define BUFFER_SIZE 256
BYTE pbBuffer[BUFFER_SIZE];
HCRYPTHASH hHash = 0;
BYTE *pbSignature = NULL;
DWORD dwSigLen;
LPTSTR szDescription = TEXT("Test Data");
DWORD i;
//获取默认提供程序的句柄。
if(!CryptAcquireContext(& hProv,NULL,NULL,PROV_RSA_FULL,0)){
printf("Error %x during CryptAcquireContext!\n", GetLastError());
goto done;
}
//将缓冲区填入测试数据。
for(i = 0 ; i < BUFFER_SIZE ; i++) {
pbBuffer[i] = (BYTE)i;
}
//创建哈希对象。
IF(!CryptCreateHash(hProv,CALG_MD5,0,0,{} hHash 989796005)){
printf("Error %x during CryptCreateHash!\n", GetLastError());
goto done;
}
//哈希缓冲区
if(!CryptHashData(hHash,pbBuffer,BUFFER_SIZE,0)){
printf("Error %x during CryptHashData!\n", GetLastError());
goto done;
}
//确定签名的大小并分配内存。
dwSigLen = 0;
if(!CryptSignHash(hHash,AT_SIGNATURE,TEXT(“”),0,NULL,& dwSigLen)){
printf("Error %x during CryptSignHash!\n", GetLastError());
if(GetLastError()!=NTE_BAD_LEN) goto done;
}
if((pbSignature = malloc(dwSigLen)) == NULL) {
printf("Out of memory!\n");
goto done;
}
//签名哈希对象。
if(!CryptSignHash(hHash,AT_SIGNATURE,szDescription,0,pbSignature,& dwSigLen)){
printf("Error %x during CryptSignHash!\n", GetLastError());
goto done;
}
//存储或传输签名,测试缓冲区和描述字符串。
...
完成:
//用于存储签名的空闲内存
if(pbSignature != NULL) free(pbSignature);
//销毁哈希对象。
if(hHash != 0) CryptDestroyHash(hHash);
//发布提供者句柄。
if(hProv != 0) CryptReleaseContext(hProv, 0);
也可以看看
CryptCreateHash, CryptDestroyHash, CryptHashData, CryptHashSessionKey, CryptVerifySignature