SHA256を調べてみたらひとまず、OPENSSLインストールして・・・
のように、何かインストールしてといった話から始まるわけですが、
諸事情によりインストールを避けたいというのとWindows限定でしか使わないということから以下のコードにたどり着いた。
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
int SHA256(BYTE* data, DWORD dataSize, BYTE* hash, DWORD* hashSize) {
int result = 0;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ goto LAST; }
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { goto LAST; }
if (!CryptHashData(hHash, data, dataSize, 0)) { goto LAST; }
if (!CryptGetHashParam(hHash, HP_HASHVAL, hash, hashSize, 0)) { goto LAST; }
result = 1;
LAST:
if (hHash) { CryptDestroyHash(hHash); }
if (hProv) { CryptReleaseContext(hProv, 0); }
return result;
}
int main() {
const char* str = "Hello SHA256";
BYTE hash[32] = { 0 };
DWORD hashSize = sizeof(hash);
if (SHA256((BYTE*)str, strlen(str), hash, &hashSize)) {
for (DWORD i = 0; i < hashSize; i++) {
printf("%02x", hash[i]);
}
printf("\n");
}
return 0;
}
ただし、CryptHashData 関数 は、非推奨とのこと。
大事な この API は非推奨です。 新規および既存のソフトウェアでは 、暗号化次世代 API の 使用を開始する必要があります。Microsoft は、今後のリリースでこの API を削除する可能性があります。 CryptHashData 関数 (wincrypt.h)
70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3
そんなわけで、書き換えるとこんな感じらしい。
#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>
#include <ntstatus.h>
#include <vector>
#include <string.h>
#pragma comment(lib, "bcrypt.lib")
std::vector<BYTE> SHA256(const BYTE* data, DWORD dataSize)
{
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
std::vector<BYTE> hash;
DWORD hashSize = 0, cbData = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
do {
// アルゴリズムプロバイダーを開く
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status)) break;
// ハッシュオブジェクトのサイズを取得
status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbData, sizeof(DWORD), &hashSize, 0);
if (!BCRYPT_SUCCESS(status)) break;
// ハッシュオブジェクトを作成
std::vector<BYTE> hashObject(cbData);
status = BCryptCreateHash(hAlg, &hHash, hashObject.data(), (ULONG)hashObject.size(), NULL, 0, 0);
if (!BCRYPT_SUCCESS(status)) break;
// データをハッシュ化
status = BCryptHashData(hHash, (PBYTE)data, dataSize, 0);
if (!BCRYPT_SUCCESS(status)) break;
// ハッシュサイズを取得
status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&hashSize, sizeof(DWORD), &cbData, 0);
if (!BCRYPT_SUCCESS(status)) break;
// 最終的なハッシュ値を取得
hash.resize(hashSize);
status = BCryptFinishHash(hHash, hash.data(), hashSize, 0);
if (!BCRYPT_SUCCESS(status)) hash.clear();
} while (false);
if (hHash) BCryptDestroyHash(hHash);
if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);
return hash;
}
int main() {
const char* str = "Hello SHA256";
DWORD dataSize = strlen(str); // 正しい入力データサイズを使用
std::vector<BYTE> hash = SHA256((BYTE*)str, dataSize);
for (BYTE b : hash) {
printf("%02x", b);
}
printf("\n");
return 0;
}
gotoで最後にまとめて解放するコードにしていたら、初期化(std::vector
70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3