小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


【VC++】CryptoAPIでSHA-256のハッシュ値を生成する

f:id:replication:20140711013907p:plain

はじめに

Visual C++ 2005の環境でCryptoAPIを使ってSHA-256のハッシュ値を生成するプログラムを書いてみました。

新版暗号技術入門 秘密の国のアリス
結城 浩
ソフトバンククリエイティブ
売り上げランキング: 5,620

SHA-256のハッシュ値を生成する

CryptoAPIを使ってSHA-256のハッシュ値を生成するには、以下の処理が必要になります。
1.CryptAcquireContextでハンドルを取得
2.CryptCreateHashでアルゴリズムを指定する
3.CryptHashDataでハッシュ対象データを登録
4.CryptGetHashParamでハッシュ値を取り出す

ポイント

SHA-256のアルゴリズムを利用するには、CryptAcquireContextのプロパイダタイプに"PROV_RSA_AES"を指定します。
続いて、CryptCreateHash APIに"CALG_SHA_256"を指定します。

サンプルプログラム

以下のサンプルプログラムでは、"hoge"という文字列から32byteのハッシュ値を生成して、コンソールに出力しています。
サンプルプログラムを動かして得られた値は、以下のようになりましたが、SHA-256 hash calculator. Online SHA-256 hash generator. Mining Bitcoin はてなブックマーク - SHA-256 hash calculator. Online SHA-256 hash generator. Mining Bitcoinで得られた結果と同じだったため、うまく動いていると思います。

ハッシュ値::ec b6 66 d7 78 72 5e c9 73 07 04 4d 64 2b f4 d1 60 aa bb 76 f5 6c 00
69 c7 1e a2 5b 1e 92 68 25

#include "stdafx.h"
#include <windows.h>

void freeResources();

HCRYPTPROV  hProv       = NULL;
HCRYPTHASH  hHash       = NULL;
PBYTE       pbHash      = NULL;

int _tmain(int argc, _TCHAR *argv[])
{

  //--------------------------------------------------------------------------
  // ハンドルの取得
  //--------------------------------------------------------------------------
  if (!CryptAcquireContext(
        &hProv,                   // CSPのハンドル
        NULL,                     // キーコンテナ名
        NULL,                     // CSP名
        PROV_RSA_AES,             // プロパイダタイプ
        CRYPT_VERIFYCONTEXT))     // 特定の鍵コンテナをオープンせずにCSPのハンドルを取得する
  {
    printf(" Error in AcquireContext 0x%08x \n", GetLastError());
    freeResources();
    return 0;
  }

  //--------------------------------------------------------------------------
  // ハッシュ値の生成
  //--------------------------------------------------------------------------
  if (!CryptCreateHash(
        hProv,                    // CSPのハンドル
        CALG_SHA_256,             // ハッシュアルゴリズム
        0,                        // ハッシュキー
        0,                        // リザーブ
        &hHash))                  // ハッシュオブジェクトのアドレス
  {
    printf("Error in CryptCreateHash 0x%08x \n", GetLastError());
    freeResources();
    return 0;
  }

  BYTE Buf[] = "hoge";  // このデータをハッシュ化する

  //--------------------------------------------------------------------------
  // ハッシュ対象データの追加
  //--------------------------------------------------------------------------
  if (!CryptHashData(
        hHash,                    // CSPのハンドル
        Buf,                      // ハッシュ対象データ
        sizeof(Buf) - 1,          // ハッシュ対象データサイズ
        0))                       // フラグ
  {
    printf("Error in CryptHashData 0x%08x \n", GetLastError());
    freeResources();
    return 0;
  }

  DWORD dwDataLen = 32; // SHA-256の場合、256bit=32byte

  // ハッシュ値格納用のバッファをアロケート
  pbHash = (BYTE *)malloc(dwDataLen);
  if (NULL == pbHash)
  {
    printf("unable to allocate memory\n");
    freeResources();
    return 0;
  }

  //--------------------------------------------------------------------------
  // ハッシュ値の取り出し
  //--------------------------------------------------------------------------
  if (!CryptGetHashParam(
        hHash,                 // CSPのハンドル
        HP_HASHVAL,            // ハッシュ値を取得する
        pbHash,                // ハッシュ値
        &dwDataLen,            // ハッシュ値のbyte数
        0))
  {
    printf("Error in CryptGetHashParam 0x%08x \n", GetLastError());
    freeResources();
    return 0;
  }

  // ハッシュ値をコンソールに出力する
  printf("ハッシュ値::");

  for (DWORD i = 0 ; i < dwDataLen ; i++)
  {
    printf("%2.2x ", pbHash[i]);
  }

  printf("\n");

  return 0;
}

// 解放処理
void freeResources()
{
  if (hHash)
  {
    CryptDestroyHash(hHash);
  }

  if (hProv)
  {
    CryptReleaseContext(hProv, 0);
  }

  if (pbHash)
  {
    free(pbHash);
  }

  return;
}