0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C++ で ハッシュ値を生成する。 Windows Cryptography API: Next Generation編

Posted at

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;
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?