Created
July 11, 2018 03:21
-
-
Save pps83/51064f120aedb3835636581cc7275f46 to your computer and use it in GitHub Desktop.
Compute sha1/md5/hmac-sha1/hmac-md5 using windows API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef _WIN32 | |
#include <windows.h> | |
#if !defined(PLATFORM_XBOX) && !defined(PLATFORM_UWP) | |
#include <wincrypt.h> | |
#else | |
#include <bcrypt.h> | |
#pragma comment(lib, "bcrypt.lib") | |
#endif | |
int computeHash(const void* data, unsigned dataSize, unsigned char hashBuf[64], const void *hmacSecret, unsigned hmacSecretSize, bool isMD5) | |
{ | |
int ret = 0; | |
const int hashBufSize = 64; | |
unsigned char hashBuf1[64] = { 0 }; | |
assert((hmacSecret && hmacSecretSize > 0) || (!hmacSecret && hmacSecretSize == 0)); | |
DWORD hashSize, hashSizeSize = sizeof(hashSize); | |
#if !defined(PLATFORM_XBOX) && !defined(PLATFORM_UWP) | |
HCRYPTPROV context; | |
if (CryptAcquireContext(&context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) | |
{ | |
HCRYPTKEY hmackey = 0; | |
if (hmacSecret) | |
{ | |
struct HmacSecretBlob | |
{ | |
BLOBHEADER header; | |
DWORD hmacSecretSize; | |
BYTE hmacSecret[1]; | |
}; | |
size_t hmacSecretBlobSize = std::max(offsetof(HmacSecretBlob, hmacSecret) + hmacSecretSize, sizeof(HmacSecretBlob)); | |
std::vector<uint8_t> blobData(hmacSecretBlobSize); | |
HmacSecretBlob* hmacSecretBlob = reinterpret_cast<HmacSecretBlob*>(blobData.data()); | |
hmacSecretBlob->header.bType = PLAINTEXTKEYBLOB; | |
hmacSecretBlob->header.bVersion = CUR_BLOB_VERSION; | |
hmacSecretBlob->header.reserved = 0; | |
hmacSecretBlob->header.aiKeyAlg = CALG_RC2; | |
hmacSecretBlob->hmacSecretSize = hmacSecretSize; | |
memcpy(hmacSecretBlob->hmacSecret, hmacSecret, hmacSecretSize); | |
if (!CryptImportKey(context, blobData.data(), blobData.size(), 0, CRYPT_IPSEC_HMAC_KEY, &hmackey)) | |
{ | |
CryptReleaseContext(context, 0); | |
return 0; | |
} | |
} | |
HCRYPTHASH hash; | |
if (CryptCreateHash(context, hmacSecret ? CALG_HMAC : (isMD5 ? CALG_MD5 : CALG_SHA1), hmackey, 0, &hash)) | |
{ | |
if (hmacSecret) | |
{ | |
HMAC_INFO info = { 0 }; | |
info.HashAlgid = isMD5 ? CALG_MD5 : CALG_SHA1; | |
if (!CryptSetHashParam(hash, HP_HMAC_INFO, (BYTE *)&info, 0)) | |
{ | |
CryptReleaseContext(context, 0); | |
CryptDestroyHash(hash); | |
return 0; | |
} | |
} | |
if (CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *)&hashSize, &hashSizeSize, 0) && hashSize <= hashBufSize) | |
{ | |
assert((isMD5 && hashSize == 16) || (!isMD5 && hashSize == 20)); // 16 bytes for MD5, 20 bytes for sha1 | |
if (CryptHashData(hash, (BYTE*)data, dataSize, 0)) | |
{ | |
if (CryptGetHashParam(hash, HP_HASHVAL, hashBuf, &hashSize, 0)) | |
ret = (int)hashSize; | |
} | |
} | |
CryptDestroyHash(hash); | |
} | |
if (hmacSecret) | |
CryptDestroyKey(hmackey); | |
CryptReleaseContext(context, 0); | |
} | |
#else | |
BCRYPT_ALG_HANDLE context; | |
if (BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&context, isMD5 ? BCRYPT_MD5_ALGORITHM : BCRYPT_SHA1_ALGORITHM, NULL, hmacSecret ? BCRYPT_ALG_HANDLE_HMAC_FLAG : 0))) | |
{ | |
BCRYPT_HASH_HANDLE hash; | |
if (BCRYPT_SUCCESS(BCryptGetProperty(context, BCRYPT_HASH_LENGTH, (PUCHAR)&hashSize, sizeof(hashSize), &hashSizeSize, 0)) && hashSize <= hashBufSize) | |
{ | |
assert((isMD5 && hashSize == 16) || (!isMD5 && hashSize == 20)); // 16 bytes for MD5, 20 bytes for sha1 | |
if (BCRYPT_SUCCESS(BCryptCreateHash(context, &hash, NULL, 0, (PUCHAR)hmacSecret, hmacSecretSize, 0))) | |
{ | |
if (BCRYPT_SUCCESS(BCryptHashData(hash, (PUCHAR)data, dataSize, 0))) | |
{ | |
if (BCRYPT_SUCCESS(BCryptFinishHash(hash, hashBuf, hashSize, 0))) | |
ret = hashSize; | |
} | |
BCryptDestroyHash(hash); | |
} | |
} | |
BCryptCloseAlgorithmProvider(context, 0); | |
} | |
#endif | |
return ret; | |
} | |
#endif // _WIN32 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment