Skip to content

Instantly share code, notes, and snippets.

@Barakat
Created January 19, 2019 14:06
Show Gist options
  • Save Barakat/e9b0f212e24cb2455cc8f47594b6ac6e to your computer and use it in GitHub Desktop.
Save Barakat/e9b0f212e24cb2455cc8f47594b6ac6e to your computer and use it in GitHub Desktop.
Hashing with Cryptography API: Next Generation (CNG)
#define _WIN32_WINNT 0x0600 // Windows Vista
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <bcrypt.h>
#include <cstddef>
#include <memory>
#include <cassert>
#pragma comment(lib, "bcrypt.lib")
static bool Checksum(LPCWSTR algorithm_id,
const void* data,
std::size_t data_size,
void* output,
std::size_t output_size)
{
NTSTATUS status;
BCRYPT_ALG_HANDLE algorithm;
status = BCryptOpenAlgorithmProvider(&algorithm, algorithm_id, nullptr, 0);
if (SUCCEEDED(status))
{
DWORD result;
#ifndef NDEBUG
DWORD hash_length;
status = BCryptGetProperty(algorithm,
BCRYPT_HASH_LENGTH,
reinterpret_cast<PUCHAR>(&hash_length),
sizeof(hash_length),
&result,
0);
assert(SUCCEEDED(status));
assert(hash_length == output_size);
#endif
DWORD object_length;
status = BCryptGetProperty(algorithm,
BCRYPT_OBJECT_LENGTH,
reinterpret_cast<PUCHAR>(&object_length),
sizeof(object_length),
&result,
0);
if (SUCCEEDED(status))
{
BCRYPT_HASH_HANDLE hash;
const auto object_value = std::make_unique<UCHAR[]>(object_length);
status = BCryptCreateHash(algorithm,
&hash,
object_value.get(),
object_length,
nullptr,
0,
0);
if (SUCCEEDED(status))
{
status = BCryptHashData(hash, reinterpret_cast<PUCHAR>(const_cast<void *>(data)), data_size, 0);
if (SUCCEEDED(status))
{
status = BCryptFinishHash(hash, reinterpret_cast<PUCHAR>(output), output_size, 0);
}
}
}
BCryptCloseAlgorithmProvider(algorithm, 0);
}
return SUCCEEDED(status);
}
bool MD5Checksum(const void* data, std::size_t data_size, void* output, std::size_t output_size)
{
return Checksum(BCRYPT_MD5_ALGORITHM, data, data_size, output, output_size);
}
bool SHA1Checksum(const void* data, std::size_t data_size, void* output, std::size_t output_size)
{
return Checksum(BCRYPT_SHA1_ALGORITHM, data, data_size, output, output_size);
}
bool SHA256Checksum(const void* data, std::size_t data_size, void* output, std::size_t output_size)
{
return Checksum(BCRYPT_SHA256_ALGORITHM, data, data_size, output, output_size);
}
void PrintHex(const void* data, std::size_t data_size)
{
const auto bytes = reinterpret_cast<const UCHAR*>(data);
for (std::size_t i = 0; i < data_size; ++i)
{
const auto byte = bytes[i];
const auto upper = byte >> 4;
const auto lower = byte & 0xf;
#define HEX_NIBBLE(n) (n <= 9 ? '0' + n : 'a' - (10 - n))
std::putchar(HEX_NIBBLE(upper));
std::putchar(HEX_NIBBLE(lower));
#undef HEX_NIBBLE
}
}
int main()
{
const auto data = "Hello world!";
const auto size = 12;
// MD5
unsigned char md5checksum[16];
MD5Checksum(data, size, md5checksum, sizeof(md5checksum));
printf("md5('%s') = ", data);
PrintHex(md5checksum, sizeof(md5checksum));
std::putchar('\n');
// SHA-1
unsigned char sha1checksum[20];
SHA1Checksum(data, size, sha1checksum, sizeof(sha1checksum));
printf("sha1('%s') = ", data);
PrintHex(sha1checksum, sizeof(sha1checksum));
std::putchar('\n');
// SHA-256
unsigned char sha256checksum[32];
SHA256Checksum(data, size, sha256checksum, sizeof(sha256checksum));
printf("sha256('%s') = ", data);
PrintHex(sha256checksum, sizeof(sha256checksum));
std::putchar('\n');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment