CryptSignHash
[New
- Windows NT]
[New
- Windows 95, OEM Service Release 2]
The CryptSignHash
function is used to sign a piece of data. Because all signature algorithms are
asymmetric and thus incredibly slow, CryptoAPI will not let data be signed
directly. Instead, you must first hash the data and then use CryptSignHash
to sign the hash value.
BOOL
CRYPTFUNC CryptSignHash(
HCRYPTHASH
hHash, |
|
DWORD dwKeySpec, |
|
LPCTSTR sDescription, |
|
DWORD dwFlags, |
|
BYTE *pbSignature, |
|
DWORD *pdwSigLen |
|
); |
|
Parameters
hHash
[in] A handle
to the hash object to be signed.
dwKeySpec
[in] The key
pair to use to sign the hash. The following keys can be specified:
AT_KEYEXCHANGE Exchange private key
AT_SIGNATURE Signature private key
The signature
algorithm used is specified when the key pair was originally created.
The only
signature algorithm that the Microsoft RSA Base Provider supports is the RSA
Public-Key algorithm.
sDescription
[in] The
string describing the data to sign. This description text is added to the hash
object before the signature is generated. Whenever the signature is
authenticated (with CryptVerifySignature
Some CSPs
(not the Microsoft RSA Base Provider) will display this description string to
the user. This lets the user confirm what he or she is signing. This protects
the user from unscrupulous applications and also reduces misunderstandings.
This
parameter can be NULL if no description string is to included in the signature.
Usually, this is only the case when the signature is performed using a
signature key that is not legally bound to the user. For example, when a
signature operation is performed with the key exchange private key as part of a
key exchange protocol, no description string is typically specified.
dwFlags
[in] The flag
values. This parameter is reserved for future use and should always be zero.
pbSignature
[out] The
buffer in which the function places the signature data.
This parameter
can be NULL if all you are doing is determining the number of bytes required
for the returned signature data.
pdwSigLen
[in/out] The
address of the signature data length. Before calling this function, the caller
should set this parameter to the length, in bytes, of the pbSignature
buffer. Upon return, this address will contain the number of bytes in the
signature data.
If the buffer
specified by pbSignature is not large enough to hold the data, the
function returns the ERROR_MORE_DATA error code (through GetLastError
If pbSignature
is NULL, then no error is returned and the function stores the size of the
data, in bytes, in the variable pointed to by pdwSigLen.
Remarks
Before
calling this function, the CryptCreateHash21HHDD_ function is then used to add the data or
session keys to the hash object.
Once this
function has been completed, the only hash function that can be called using
the hHash handle is the CryptDestroyHash
Return Values
If the
function succeeds, the return value is nonzero.
If the
function fails, the return value is zero. To retrieve extended error
information, use the GetLastError
The following
table lists the error codes most commonly returned by the GetLastError
function. The error codes prefaced by NTE are generated by the particular CSP
you are using.
Error |
Description |
ERROR_INVALID_HANDLE |
One of the
parameters specifies an invalid handle. |
ERROR_INVALID_PARAMETER |
One of the
parameters contains an invalid value. This is most often an illegal pointer. |
NTE_BAD_ALGID |
The hHash
handle specifies an algorithm that this CSP does not support. |
NTE_BAD_FLAGS |
The dwFlags
parameter is nonzero. |
NTE_BAD_HASH |
The hash
object specified by the hHash parameter is invalid. |
NTE_BAD_UID |
The CSP
context that was specified when the hash object was created cannot be found. |
NTE_NO_KEY |
The private
key specified by dwKeySpec does not exist. |
NTE_NO_MEMORY |
The CSP ran
out of memory during the operation. |
Example
#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;
// Get handle to the default provider.
if(!CryptAcquireContext(&hProv, NULL, NULL,
PROV_RSA_FULL, 0)) {
printf("Error %x during CryptAcquireContext!\n",
GetLastError());
goto done;
}
// Fill buffer with test data.
for(i = 0 ; i < BUFFER_SIZE ; i++) {
pbBuffer[i] = (BYTE)i;
}
// Create hash object.
if(!CryptCreateHash(hProv, CALG_MD5, 0, 0,
&hHash)) {
printf("Error %x during CryptCreateHash!\n", GetLastError());
goto done;
}
// Hash buffer.
if(!CryptHashData(hHash, pbBuffer, BUFFER_SIZE, 0))
{
printf("Error %x during CryptHashData!\n", GetLastError());
goto done;
}
// Determine size of signature and allocate memory.
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;
}
// Sign hash object.
if(!CryptSignHash(hHash, AT_SIGNATURE,
szDescription, 0, pbSignature, &dwSigLen)) {
printf("Error %x during CryptSignHash!\n", GetLastError());
goto done;
}
// Store or transmit the signature, test buffer, and
description string.
...
done:
// Free memory used to store signature.
if(pbSignature != NULL) free(pbSignature);
// Destroy hash object.
if(hHash != 0) CryptDestroyHash(hHash);
// Release provider handle.
if(hProv != 0) CryptReleaseContext(hProv, 0);
See Also