C, C++の標準ライブラリでは、SHA系アルゴリズムを生成するクラス、関数が、提供されていないです。
Windowsでは、OSが提供している CryptoAPIの中にSHA系アルゴリズムを生成する関数が提供されていますが、今回、改めて調べたら非推奨になっていたので、今回は、Cryptography API: Next Generation を使用して、ハッシュ値を生成してみました。
サンプル
SHA1, SHA256アルゴリズムでハッシュ値を生成し、出力するプログラムです。
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <bcrypt.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
NTSTATUS CreateHash(LPCWSTR pszAlgId, std::vector<UCHAR> &input, std::vector<UCHAR> &output) {
NTSTATUS status = STATUS_UNSUCCESSFUL;
BCRYPT_ALG_HANDLE hAlg = NULL;
DWORD cbData = 0, cbHash = 0, cbHashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL;
PBYTE pbOutput = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
do {
//open an algorithm handle
status = BCryptOpenAlgorithmProvider(&hAlg, pszAlgId, NULL, 0);
if (!NT_SUCCESS(status)) {
break;
}
//calculate the size of the buffer to hold the hash object
status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0);
if (!NT_SUCCESS(status)) {
break;
}
//allocate the hash object on the heap
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
if (NULL == pbHashObject) {
status = STATUS_UNSUCCESSFUL;
break;
}
//calculate the length of the hash
status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbHash, sizeof(DWORD), &cbData, 0);
if (!NT_SUCCESS(status)) {
break;
}
//allocate the hash buffer on the heap
pbOutput = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
if (NULL == pbOutput) {
status = STATUS_UNSUCCESSFUL;
break;
}
//create a hash
status = BCryptCreateHash(hAlg, &hHash, pbHashObject, cbHashObject, NULL, 0, 0);
if (!NT_SUCCESS(status)) {
break;
}
//hash some data
status = BCryptHashData(hHash, input.data(), input.size(), 0);
if (!NT_SUCCESS(status)) {
break;
}
//close the hash
status = BCryptFinishHash(hHash, pbOutput, cbHash, 0);
if (!NT_SUCCESS(status)) {
break;
}
output.resize(cbHash);
PBYTE p = pbOutput;
for (size_t i = 0; i < cbHash; i++) {
output.at(i) = *p;
p++;
}
if (hAlg) {
BCryptCloseAlgorithmProvider(hAlg, 0);
}
if (hHash) {
BCryptDestroyHash(hHash);
}
if (pbHashObject) {
HeapFree(GetProcessHeap(), 0, pbHashObject);
}
if (pbOutput) {
HeapFree(GetProcessHeap(), 0, pbOutput);
}
} while (0);
return status;
}
int main()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
std::string str("Hello World");
std::vector<UCHAR> input(str.begin(), str.end());
std::vector<UCHAR> hash1;
status = CreateHash(BCRYPT_SHA1_ALGORITHM, input, hash1);
if (!NT_SUCCESS(status)) {
std::cout << "Error: " << status << std::endl;
return -1;
}
std::cout << "SHA1" << std::endl;
for (size_t i = 0; i < hash1.size(); i++) {
std::cout << std::hex << (int)hash1.at(i);
}
std::cout << std::endl;
std::vector<UCHAR> hash2;
status = CreateHash(BCRYPT_SHA256_ALGORITHM, input, hash2);
if ( !NT_SUCCESS(status) ) {
std::cout << "Error: " << status << std::endl;
return -1;
}
std::cout << "SHA256" << std::endl;
for (size_t i = 0; i < hash2.size(); i++) {
std::cout << std::hex << (int)hash2.at(i);
}
std::cout << std::endl;
return 0;
}