C++でSHA256

C++

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 hashObject(cbData);)をバイパスしてますエラーがでるので あまりきれいじゃなけど、初期化をまとめたかったので、この書き方に・・・

70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3
投稿日時: 2024-09-22 10:41:22
更新日時: 2024-09-22 10:43:22

最近の投稿

タグ

アーカイブ

その他