ホーム 主筆 その他ソフト その他情報 Syuhitu.org English

Windows関連

スクリーンセーバー作成法

半透明ウインドウの性能

bootfont.bin

キャビネット形式

ウインドウスタイルをいじる

Java製ソフトをServiceに登録する

イベントログにメッセージを出力する

コントロールパネルにアイコンを追加する

スクリプトによる拡張1

スクリプトによる拡張2

ガジェットの作成

大容量メモリ

メモリ搭載量の下限に挑む

スパースファイルにする

表示されるアイコンの種類を調べてみた

メモリマップIOとエラー処理

ファイルを作る順番と速度の関係

Cryptography API: Next Generationを使う

Windows 10のアクセントカラー

iSCSIディスクにバックアップを取る

サーバプロセスを分離して実装する

サーバプロセスを分離して実装する - F#

レジストリに大量に書き込む

Solaris関連

OpenGL

Solaris設定

ディレクトリの読み込み

主筆プラグイン開発

マルチスレッドでの開発

door

音を出す

Blade100の正しい虐め方

パッケージの作成

画像入出力

BMPファイル

ICOファイル

ANIファイル

JPEGファイル

減色アルゴリズム

減色アルゴリズムの並列化

その他アルゴリズムなど

自由軸回転

Base64

文字列操作

CPU利用率の取得

正規表現ライブラリ

メタボールを作る

メタボールを作る2

正規表現とNFA・DFA

C言語の構文解析

液晶ディスプレイを解体してみた

iSCSIの理論と実装

単一フォルダにファイルを沢山作る

USB-HUBのカスケード接続

SafeIntの性能

VHDファイルのフォーマット

USBメモリに書き込み続けてみた

CNG:ハッシュアルゴリズムの比較

2016年1月31日公開

CNGで使えるハッシュアルゴリズムの一覧を示す。

標準で使えるハッシュアルゴリズム

ハッシュアルゴリズムは、BCryptOpenAlgorithmProvider関数の第二引数で選択する。

標準では下記のものが定義されている。

定数 ハッシュアルゴリズム ダイジェスト長
BCRYPT_MD2_ALGORITHM MD2 128bit/16byte
BCRYPT_MD4_ALGORITHM MD4 128bit/16byte
BCRYPT_MD5_ALGORITHM MD5 128bit/16byte
BCRYPT_SHA1_ALGORITHM SHA1 160bit/20byte
BCRYPT_SHA256_ALGORITHM SHA256 256bit/32byte
BCRYPT_SHA384_ALGORITHM SHA384 384bit/48byte
BCRYPT_SHA512_ALGORITHM SHA512 512bit/64byte

検索したところ、2016年現在ではセキュリティ的な用途ではMD2、MD4、MD5、SHA1は使用しない方がいいらしい。

どうで何を選んでもCNGを使うプログラムからすれば何も変わりはないのだから、SHA256以上にしておけばよいと思われる。

ハッシュ値算出用のオブジェクトのサイズ

CNGでは、ハッシュ値を算出用のオブジェクトなるものを作る必要があり、そのためにバッファを確保してやらなければならない。アルゴリズムごとに必要になるバッファサイズが異なるようなので、そのサイズを調べてみた。Windows 10での結果である。

ハッシュアルゴリズム オブジェクトサイズ
MD2 270byte
MD4 270byte
MD5 270byte
SHA1 278byte
SHA256 286byte
SHA384 382byte
SHA512 382byte

当然だが、上記の値をプログラム中に直接記述するべきではない。BCryptGetProperty関数で取得する。

実行時間

気になるのはやはり速度である。

ごく単純に測定してみた。

ハッシュアルゴリズム 1000万回繰り返した時の実行時間
MD2 565,750ms
MD4 8,813ms
MD5 12,765ms
SHA1 16,438ms
SHA256 29,125ms
SHA384 30,953ms
SHA512 30,656ms

環境としてはOSがWindows 10、CPUがCore i7-5930K 3.5GHzである。ハッシュ化したデータはランダムな512バイトのデータである。

参考までに実行したプログラムを示す。

#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <Windows.h>
 
// CNGのヘッダファイル
#include <Bcrypt.h>

int _tmain(int argc, _TCHAR* argv[])
{
  BCRYPT_ALG_HANDLE hAlgorithm;	// CNGのアルゴリズムプロバイダのハンドル
  BCRYPT_HASH_HANDLE hHash;		// ハッシュ値算出用オブジェクトのハンドル
  unsigned long ObjectSize = 0;	// ハッシュオブジェクトのサイズ
  unsigned long Result = 0;		// 作業用
  unsigned int HashLength = 0;	// ハッシュ値のサイズ
  unsigned char vSourceData[512] = "";
  const TCHAR *vAlgorithmType[] = {
    BCRYPT_MD2_ALGORITHM,
    BCRYPT_MD4_ALGORITHM,
    BCRYPT_MD5_ALGORITHM,
    BCRYPT_SHA1_ALGORITHM,
    BCRYPT_SHA256_ALGORITHM,
    BCRYPT_SHA384_ALGORITHM,
    BCRYPT_SHA512_ALGORITHM
  };
  for ( int i = 0; i < sizeof( vSourceData ); i++ )
    vSourceData[i] = rand();
 
  for ( int i = 0; i < _countof( vAlgorithmType ); i++ ) {
    // アルゴリズムプロバイダを取得する
    BCryptOpenAlgorithmProvider(
      &hAlgorithm, vAlgorithmType[i], MS_PRIMITIVE_PROVIDER, 0
    );
    printf( "アルゴリズム = %S\n", vAlgorithmType[i] );
 
    // ハッシュ値算出用のオブジェクトのサイズを取得する
    BCryptGetProperty(
      hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)( &ObjectSize ), sizeof( ObjectSize ), &Result, 0
    );
 
    // ハッシュ値のサイズを取得する
    BCryptGetProperty(
      hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)( &HashLength ), sizeof( HashLength ), &Result, 0
    );
 
    // ハッシュ値算出用のオブジェクトのメモリ領域を確保する
    unsigned char *pHashObject = (PUCHAR)calloc( ObjectSize, sizeofunsigned char ) );
    // ハッシュ値を取得するためのバッファを確保する
    unsigned char *pHashValue = (PUCHAR)calloc( HashLength, sizeofunsigned char ) );
 
    unsigned long StartTick = GetTickCount();
 
    for ( int j = 0; j < 10000000; j++ ) {
      BCryptCreateHash( hAlgorithm, &hHash, pHashObject, ObjectSize, nullptr, 0, 0 );
      BCryptHashData( hHash, vSourceData, sizeof( vSourceData ), 0 );
      BCryptFinishHash( hHash, pHashValue, HashLength, 0 );
      BCryptDestroyHash( hHash );
    }
    unsigned long EndTick = GetTickCount();
    printf( "実行時間(ms) = %d\n", EndTick - StartTick );
 
    // アルゴリズムプロバイダを破棄する
    BCryptCloseAlgorithmProvider( hAlgorithm, 0 );
 
    // メモリ領域を解放する
    free( pHashObject );
    free( pHashValue );
  }
  return 0;
}

MD2が極端に遅い理由は知らない。

なお、bitcoin用のASIC1つで数Gハッシュ/秒なとと言っているので、そういった用途ではCPU1つでは到底太刀打ちできない。SHA-256だと、たとえクロックを2倍の7GHzにして6コア全部をつぎ込んでも、400万回がせいぜいである。まぁ、どうでもいいけど。

 

<< 「Cryptography API: Next Generationを使う」に戻る


連絡先 - サイトマップ - 更新履歴
Copyright (C)  2000 - 2016 nabiki_t All Rights Reserved.