记录一下hash和hmac的算法.
static void Hash(ALG_ID algId, BYTE* pData, DWORD dataLength, BYTE* pCode,DWORD* pdwLength)
{
HCRYPTPROV hProv = NULL;
BOOL blRet = FALSE;
blRet=CryptAcquireContext(&hProv,
NULL, NULL,
PROV_RSA_FULL, 0);
HCRYPTHASH hHash = NULL;
blRet=CryptCreateHash(hProv,
algId, 0, 0, & hHash);
blRet = CryptHashData(hHash, pData, dataLength, 0);
DWORD dwLen = 20;
blRet = CryptGetHashParam(hHash, HP_HASHVAL,NULL, &dwLen, 0);
blRet=CryptGetHashParam(hHash, HP_HASHVAL, pCode, &dwLen, 0);
CryptDestroyKey(hHash);
CryptReleaseContext(hProv,0);
*pdwLength = dwLen;
}
static void MyHMAC(ALG_ID algId, BYTE* _pKey, DWORD _dwKeyLength, BYTE* pData,DWORD dwDataLength,
BYTE* pHMAC, DWORD* pdwHMACLength)
{
const DWORD B = 64; //MD5和SHA这个值是64
//首先第一步: 如果Key不足B长度,尾部填充0至B长度。
//如果key长度大于B,则先将key进行HASH,然后结果如果小于B,尾部填充至B长度。
BYTE fillKey[200]; DWORD dwFillKey = 0;
if (_dwKeyLength > 64)
{
Hash(algId, _pKey, _dwKeyLength, fillKey, &dwFillKey);
}
else
{
dwFillKey = _dwKeyLength;
memcpy(fillKey, _pKey, _dwKeyLength);
}
for (int i = dwFillKey; i < B; i++)
fillKey[i] = 0;
/
//第二步,填充ipad和opad。 都是B长度。
//拷贝FillKey到ipad和opad,然后进行异或运算
BYTE k_ipad[B], k_opad[B];
memcpy(k_ipad, fillKey, B);
memcpy(k_opad, fillKey, B);
for (int i = 0; i < B; i++)
{
k_ipad[i]^= 0x36;
k_opad[i] ^= 0x5c;
}
//将ipad与data连接起来进行hash
DWORD dwConLength1 = B + dwDataLength;
BYTE* pCon1 = new BYTE[dwConLength1];
memcpy(pCon1, k_ipad, B);
memcpy(pCon1 + B, pData, dwDataLength);
BYTE HashSha1[200]; DWORD dwHashLen1 = 0;
Hash(algId, pCon1, dwConLength1, HashSha1, &dwHashLen1);
/
//hash的长度,应该是固定的
int HashLength = dwHashLen1;
//将opad与上次hash的结果连接起来,进行hash ,结果就是hmac
DWORD dwConLength2 = B + HashLength;
BYTE* pCon2 = new BYTE[dwConLength2];
memcpy(pCon2, k_opad, B);
memcpy(pCon2 + B, HashSha1, HashLength);
BYTE HashSha2[200]; DWORD dwHashLen2 = 0;
Hash(algId, pCon2, dwConLength2, HashSha2, &dwHashLen2);
memcpy(pHMAC, HashSha2, HashLength);
*pdwHMACLength = dwHashLen2;
}