RE: Creating an HMAC for a string using a base64 encoded key
- From: David Moore <DavidNM@xxxxxxxxxxxxxxxx>
- Date: Sun, 20 Aug 2006 08:54:02 -0700
I'm all set. I grabbed the importkey snippet from the CyrptImportKey getting
invalid ALGID thread.
do this instead of the first hash / derive key of the "password"
HCRYPTKEY ImportKey(HCRYPTPROV hProv, BYTE *key, int keylen)
{
PLAINTEXTKEYBLOBSTRUCT *KeyBlob=NULL;
HCRYPTKEY hKey = NULL;
KeyBlob =(PLAINTEXTKEYBLOBSTRUCT *)LocalAlloc(LPTR,
sizeof(PLAINTEXTKEYBLOBSTRUCT) + keylen);
if (KeyBlob == NULL) {
return NULL;
}
KeyBlob->bh.bType = PLAINTEXTKEYBLOB;
KeyBlob->bh.bVersion=CUR_BLOB_VERSION;
KeyBlob->bh.reserved=0;
KeyBlob->bh.aiKeyAlg=CALG_RC2;
KeyBlob->dwKeyLen=(DWORD)keylen;
memcpy(KeyBlob +1,key,keylen);
CryptImportKey(hProv,
(BYTE*) KeyBlob,
sizeof(PLAINTEXTKEYBLOBSTRUCT),
0,
CRYPT_IPSEC_HMAC_KEY,
&hKey) ;
LocalFree(KeyBlob);
return hKey;
}
"David Moore" wrote:
Hi,.
I'm looking at
http://windowssdk.msdn.microsoft.com/en-us/library/ms726871.aspx and
struggling to use this code sample correctly. I have a base64 encoded string
containing the key to sign a string with. I can decode the base64 key
correctly which yields a 16 byte key using some of my own code. I have
verified that against independent versions of base64 decoders on the net.
Can anybody give me some guidance why I'm getting incorrect values? The
person i'm working with has basically given me test values and results. They
match the results I see when I download a test program. He is using python's
crypto library.
my suspicion is that I need to import the key directly rather then hashing
it as in the example.
my code flow is as follows:
#define SIGNATURE_KEY_SIZE 16
string CIMPacketHandler::SignPayload(const string & string_to_sign, const
string & signature_key)
{
string rval=_T("");
string tmp = _T("");
// 2a) decode signature_key
DWORD nBufLen = signature_key.length();
BYTE bytEncryptionKey[SIGNATURE_KEY_SIZE];
Base64Coder mydecoder;
mydecoder.Decode(signature_key.c_str());
memcpy(bytEncryptionKey, mydecoder.DecodedMessage(), SIGNATURE_KEY_SIZE);
//--------------------------------------------------------------------
// Declare variables.
//
// hProv: Handle to a cryptographic service provider (CSP).
// This example retrieves the default provider for
// the PROV_RSA_FULL provider type.
// hHash: Handle to the hash object needed to create a hash.
// hKey: Handle to a symmetric key. This example creates a
// key for the RC4 algorithm.
// hHmacHash: Handle to an HMAC hash.
// pbHash: Pointer to the hash.
// dwDataLen: Length,in bytes, of the hash.
// bytEncryptionKey:Password string used to create a symmetric key.
// string_to_sign: Message string to be hashed.
// HmacInfo: Instance of an HMAC_INFO structure that contains
// information about the HMAC hash.
//
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHmacHash = NULL;
PBYTE pbHash = NULL;
DWORD dwDataLen = 0;
//BYTE Data1[] = {0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64};
//BYTE Data2[] = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_INFO HmacInfo;
//--------------------------------------------------------------------
// Zero the HMAC_INFO structure and use the SHA1 algorithm for
// hashing.
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
HmacInfo.HashAlgid = CALG_SHA1;
//--------------------------------------------------------------------
// Acquire a handle to the default RSA cryptographic service provider.
if (!CryptAcquireContext(
&hProv, // handle of the CSP
NULL, // key container name
NULL, // CSP name
PROV_RSA_FULL, // provider type
CRYPT_VERIFYCONTEXT)) // no key access is requested
{
printf(" Error in AcquireContext 0x%08x \n",
GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Derive a symmetric key from a hash object by performing the
// following steps:
// 1. Call CryptCreateHash to retrieve a handle to a hash object.
// 2. Call CryptHashData to add a text string (password) to the
// hash object.
// 3. Call CryptDeriveKey to create the symmetric key from the
// hashed password derived in step 2.
// You will use the key later to create an HMAC hash object.
if (!CryptCreateHash(
hProv, // handle of the CSP
CALG_SHA1, // hash algorithm to use
0, // hash key
0, // reserved
&hHash)) // address of hash object handle
{
printf("Error in CryptCreateHash 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptHashData(
hHash, // handle of the hash object
bytEncryptionKey, // password to hash
SIGNATURE_KEY_SIZE, // number of bytes of data to add
0)) // flags
{
printf("Error in CryptHashData 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptDeriveKey(
hProv, // handle of the CSP
CALG_RC4, // algorithm ID
hHash, // handle to the hash object
0, // flags
&hKey)) // address of the key handle
{
printf("Error in CryptDeriveKey 0x%08x \n",
GetLastError());
goto ErrorExit;
}
//if(!CryptImportKey(hProv, bytEncryptionKey, SIGNATURE_KEY_SIZE, NULL, 0,
&hKey))
//{
// printf("Error in CryptImportKey 0x%08x \n",
// GetLastError());
// goto ErrorExit;
//}
//--------------------------------------------------------------------
// Create an HMAC by performing the following steps:
// 1. Call CryptCreateHash to create a hash object and retrieve
// a handle to it.
// 2. Call CryptSetHashParam to set the instance of the HMAC_INFO
// structure into the hash object.
// 3. Call CryptHashData to compute a hash of the message.
// 4. Call CryptGetHashParam to retrieve the size, in bytes, of
// the hash.
// 5. Call malloc to allocate memory for the hash.
// 6. Call CryptGetHashParam again to retrieve the HMAC hash.
if (!CryptCreateHash(
hProv, // handle of the CSP.
CALG_HMAC, // HMAC hash algorithm ID
hKey, // key for the hash (see above)
0, // reserved
&hHmacHash)) // address of the hash handle
{
printf("Error in CryptCreateHash 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptSetHashParam(
hHmacHash, // handle of the HMAC hash object
HP_HMAC_INFO, // setting an HMAC_INFO object
(BYTE*)&HmacInfo, // the HMAC_INFO object
0)) // reserved
{
printf("Error in CryptSetHashParam 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptHashData(
hHmacHash, // handle of the HMAC hash object
(BYTE*)string_to_sign.c_str(), // message to hash
string_to_sign.length(), // number of bytes of data to add
0)) // flags
{
printf("Error in CryptHashData 0x%08x \n",
GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Call CryptGetHashParam twice. Call it the first time to retrieve
// the size, in bytes, of the hash. Allocate memory. Then call
// CryptGetHashParam again to retrieve the hash value.
if (!CryptGetHashParam(
hHmacHash, // handle of the HMAC hash object
HP_HASHVAL, // query on the hash value
NULL, // filled on second call
&dwDataLen, // length, in bytes,of the hash
0))
{
printf("Error in CryptGetHashParam 0x%08x \n",
GetLastError());
goto ErrorExit;
}
pbHash = (BYTE*)malloc(dwDataLen);
if(NULL == pbHash)
{
printf("unable to allocate memory\n");
goto ErrorExit;
}
if (!CryptGetHashParam(
hHmacHash, // handle of the HMAC hash object
HP_HASHVAL, // query on the hash value
pbHash, // pointer to the HMAC hash value
&dwDataLen, // length,in bytes, of the hash
0))
{
printf("Error in CryptGetHashParam 0x%08x \n", GetLastError());
goto ErrorExit;
}
// encode the hash to base64
//printf("The hash is: ");
for(DWORD i = 0 ; i < dwDataLen ; i++)
{
tmp.Format(_T("%2x"), pbHash[i]);
rval += tmp;
}
//printf("%2x ",pbHash[i]);
//}
//printf("\n");
// Free resources.
ErrorExit:
if(hHmacHash)
CryptDestroyHash(hHmacHash);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hProv)
CryptReleaseContext(hProv, 0);
if(pbHash)
free(pbHash);
return rval;
}
- Follow-Ups:
- RE: Creating an HMAC for a string using a base64 encoded key
- From: "Jeffrey Tan[MSFT]"
- RE: Creating an HMAC for a string using a base64 encoded key
- References:
- Creating an HMAC for a string using a base64 encoded key
- From: David Moore
- Creating an HMAC for a string using a base64 encoded key
- Prev by Date: Creating an HMAC for a string using a base64 encoded key
- Next by Date: RE: Creating an HMAC for a string using a base64 encoded key
- Previous by thread: Creating an HMAC for a string using a base64 encoded key
- Next by thread: RE: Creating an HMAC for a string using a base64 encoded key
- Index(es):
Relevant Pages
|