ホーム 主筆 その他ソフト その他情報 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年2月28日公開

実装したアルゴリズムプロバイダをインストールした後、それが実際にちゃんと登録されたのかどうかを調べる必要がある。

そうでなくても、今何が使えて何が使えないのかを調べるすべが必要だ。ということで、登録済みのアルゴリズムプロバイダにつて、一覧を取得して表示する方法を示す。

プロバイダの一覧を取得

プロバイダの一覧は、BCryptEnumRegisteredProviders関数で取得できる。

ありがたいことにこの関数の仕様は単純だ。

CRYPT_PROVIDERS *pCryptProv = NULL;
unsigned long CryptProvBufSize = 0;

// プロバイダ名を取得する
r = BCryptEnumRegisteredProviders(
  &CryptProvBufSize,
  &pCryptProv
);

// プロバイダ名を表示する
for ( unsigned int i = 0; i < pCryptProv->cProviders; i++ )
  printf( "  %S\n", pCryptProv->rgpszProviders[i] );

// バッファを開放する
BCryptFreeBuffer( pCryptProv );

CRYPT_PROVIDERS構造体のポインタを渡すと、CRYPT_PROVIDERS構造体のオブジェクトを確保してそのアドレスを返してくる。使い終わったら BCryptFreeBuffer関数でメモリ領域を解放する。

アルゴリズムの一覧を取得

アルゴリズムの一覧は、BCryptEnumAlgorithms関数で取得できる。

プロバイダ名の取得と同じ様なものだが、引数にアルゴリズムのクラスを指定してやらなければならない。

BCRYPT_ALGORITHM_IDENTIFIER *pIdent = NULL;

// 取得するアルゴリズムのクラス
DWORD AlgOpe[] = {
  BCRYPT_CIPHER_OPERATION,                // 対称暗号
  BCRYPT_HASH_OPERATION,                  // ハッシュ
  BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION, // 公開鍵暗号
  BCRYPT_SECRET_AGREEMENT_OPERATION,      // 鍵生成
  BCRYPT_SIGNATURE_OPERATION,             // 署名
  BCRYPT_RNG_OPERATION                    // 乱数生成
};

// 以下は表示用の文字列
char *pAlgName[] = {
  "BCRYPT_CIPHER_OPERATION",
  "BCRYPT_HASH_OPERATION",
  "BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION",
  "BCRYPT_SECRET_AGREEMENT_OPERATION",
  "BCRYPT_SIGNATURE_OPERATION",
  "BCRYPT_RNG_OPERATION"
};

// アルゴリズムのクラスごとに情報を取得する
for ( unsigned int i = 0; i < _countof( AlgOpe ); i++ ) {
  printf( "  アルゴリズムのクラス = %s\n", pAlgName[i] );
 
// アルゴリズム名の一覧を取得する
r = BCryptEnumAlgorithms(
  AlgOpe[i],  // 取得するアルゴリズムのクラスを指定する
  &Algcnt,    // 取得されたアルゴリズムの個数
  &pIdent,    // アルゴリズムの情報
  0
);
 
for ( unsigned int j = 0; j < Algcnt; j++ )
  printf( "    アルゴリズム名 = %S\n", pIdent[j].pszName );

BCryptFreeBuffer( pIdent );

対称暗号だの、公開鍵暗号だのといった種類を指定してやらなければならないことを除いて、やっていること自体はプロバイダ名の一覧を取得する場合とそう大して変わりはない。

特定のアルゴリズムをサポートするプロバイダ名の取得

ここまででプロバイダ名の一覧とアルゴリズム名の一覧は取得できた。

しかし、どのプロバイダでどのアルゴリズムをサポートするのか、その対応関係がわからない。それを取得するのがBCryptEnumProviders関数である。

BCryptEnumProviders関数は、アルゴリズム名を指定するとそのアルゴリズムをサポートするプロバイダの名称を教えてくれる関数である。

BCRYPT_PROVIDER_NAME *pProvName = NULL;
unsigned long ProvNameCnt = 0;

// 当該のアルゴリズムをサポートするプロバイダ名を取得する
r = BCryptEnumProviders( L"AES", &ProvNameCnt, &pProvName, 0 );
 
// プロバイダ名を表示する
for ( unsigned int k = 0; k < ProvNameCnt; k++ )
  printf( "      %S\n", pProvName[k].pszProviderName );

BCryptFreeBuffer( pProvName );

アルゴリズム名の指定が必須であることを除けば、プロバイダ名の一覧の取得とさして違いはない。

全アルゴリズム名・プロバイダ名の列挙

上記を組み合わせれば、すべてのアルゴリズム名とプロバイダ名の一覧を列挙することができるようになる。

// 登録されているプロバイダ名の一覧を取得する
void Enumlate()
{
  CRYPT_PROVIDERS *pCryptProv = NULL;
  unsigned long CryptProvBufSize = 0;
  unsigned long Algcnt;
  BCRYPT_ALGORITHM_IDENTIFIER *pIdent = NULL;

  // 取得するアルゴリズムのクラス
  DWORD AlgOpe[] = {
    BCRYPT_CIPHER_OPERATION,
    BCRYPT_HASH_OPERATION,
    BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION,
    BCRYPT_SECRET_AGREEMENT_OPERATION,
    BCRYPT_SIGNATURE_OPERATION,
    BCRYPT_RNG_OPERATION
  };

  // アルゴリズムのクラスの名称
  char *pAlgName[] = {
    "BCRYPT_CIPHER_OPERATION",
    "BCRYPT_HASH_OPERATION",
    "BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION",
    "BCRYPT_SECRET_AGREEMENT_OPERATION",
    "BCRYPT_SIGNATURE_OPERATION",
    "BCRYPT_RNG_OPERATION"
  };
  BCRYPT_PROVIDER_NAME *pProvName = NULL;
  unsigned long ProvNameCnt = 0;
 
 
  printf( "\n*** プロバイダの一覧 ************************************\n" );
 
  // プロバイダ名を取得する
  NTSTATUS r = BCryptEnumRegisteredProviders(
    &CryptProvBufSize,  // 確保されたバッファのサイズ
    &pCryptProv         // プロバイダ名の情報
  );
  if ( r != 0 )
    printf( "BCryptEnumRegisteredProviders失敗\n" );
 
  // プロバイダ名を表示する
  for ( unsigned int i = 0; i < pCryptProv->cProviders; i++ )
    printf( "  %S\n", pCryptProv->rgpszProviders[i] );
 
  // バッファを開放する
  BCryptFreeBuffer( pCryptProv );


 
  printf( "\n*** アルゴリズムの一覧 ************************************\n" );
 
  // アルゴリズムのクラスごとに情報を取得する
  for ( unsigned int i = 0; i < _countof( AlgOpe ); i++ ) {
    printf( "  アルゴリズムのクラス = %s\n", pAlgName[i] );
 
    // アルゴリズム名の一覧を取得する
    r = BCryptEnumAlgorithms(
      AlgOpe[i],  // 取得するアルゴリズムのクラスを指定する
      &Algcnt,    // 取得されたアルゴリズムの個数
      &pIdent,    // アルゴリズムの情報
      0
     );
    if ( r != 0 )
      printf( "BCryptEnumAlgorithms失敗\n" );

    // アルゴリズムごとに、サポートするプロバイダ名を取得する
    for ( unsigned int j = 0; j < Algcnt; j++ ) {
      printf( "    アルゴリズム名 = %S\n", pIdent[j].pszName );
 
      // 当該のアルゴリズムをサポートするプロバイダ名を取得する
      r = BCryptEnumProviders(
        pIdent[j].pszName,  // 情報を取得するアルゴリズムの名前
        &ProvNameCnt,       // 取得されたプロバイダ名の個数
        &pProvName,         // プロバイダ名
        0
      );
      if ( r != 0 )
        printf( "BCryptEnumProviders失敗\n" );
 
      // プロバイダ名を表示する
      for ( unsigned int k = 0; k < ProvNameCnt; k++ )
        printf( "      %S\n", pProvName[k].pszProviderName );
      BCryptFreeBuffer( pProvName );

    }

    BCryptFreeBuffer( pIdent );
  }
 
 
}

実行例

上記を実行すると、以下のような結果が得られる。

*** プロバイダの一覧 ************************************
  Microsoft Key Protection Provider
  Microsoft Passport Key Storage Provider
  Microsoft Platform Crypto Provider
  Microsoft Primitive Provider
  Microsoft Smart Card Key Storage Provider
  Microsoft Software Key Storage Provider
  Microsoft SSL Protocol Provider
  Windows Client Key Protection Provider

*** アルゴリズムの一覧 ************************************
  アルゴリズムのクラス = BCRYPT_CIPHER_OPERATION
    アルゴリズム名 = AES
      Microsoft Primitive Provider
    アルゴリズム名 = 3DES
      Microsoft Primitive Provider
    アルゴリズム名 = 3DES_112
      Microsoft Primitive Provider
    アルゴリズム名 = XTS-AES
      Microsoft Primitive Provider
    アルゴリズム名 = DESX
      Microsoft Primitive Provider
    アルゴリズム名 = DES
      Microsoft Primitive Provider
    アルゴリズム名 = RC2
      Microsoft Primitive Provider
    アルゴリズム名 = RC4
      Microsoft Primitive Provider
  アルゴリズムのクラス = BCRYPT_HASH_OPERATION
    アルゴリズム名 = SHA256
      Microsoft Primitive Provider
    アルゴリズム名 = SHA384
      Microsoft Primitive Provider
    アルゴリズム名 = SHA512
      Microsoft Primitive Provider
    アルゴリズム名 = SHA1
      Microsoft Primitive Provider
    アルゴリズム名 = MD5
      Microsoft Primitive Provider
    アルゴリズム名 = MD4
      Microsoft Primitive Provider
    アルゴリズム名 = MD2
      Microsoft Primitive Provider
    アルゴリズム名 = AES-GMAC
      Microsoft Primitive Provider
    アルゴリズム名 = AES-CMAC
      Microsoft Primitive Provider
  アルゴリズムのクラス = BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
    アルゴリズム名 = RSA
      Microsoft Primitive Provider
  アルゴリズムのクラス = BCRYPT_SECRET_AGREEMENT_OPERATION
    アルゴリズム名 = DH
      Microsoft Primitive Provider
    アルゴリズム名 = ECDH_P256
      Microsoft Primitive Provider
    アルゴリズム名 = ECDH_P384
      Microsoft Primitive Provider
    アルゴリズム名 = ECDH_P521
      Microsoft Primitive Provider
    アルゴリズム名 = ECDH
      Microsoft Primitive Provider
  アルゴリズムのクラス = BCRYPT_SIGNATURE_OPERATION
    アルゴリズム名 = RSA_SIGN
      Microsoft Primitive Provider
    アルゴリズム名 = ECDSA_P256
      Microsoft Primitive Provider
    アルゴリズム名 = ECDSA_P384
      Microsoft Primitive Provider
    アルゴリズム名 = ECDSA_P521
      Microsoft Primitive Provider
    アルゴリズム名 = ECDSA
      Microsoft Primitive Provider
    アルゴリズム名 = DSA
      Microsoft Primitive Provider
  アルゴリズムのクラス = BCRYPT_RNG_OPERATION
    アルゴリズム名 = RNG
      Microsoft Primitive Provider
      Microsoft Platform Crypto Provider
    アルゴリズム名 = FIPS186DSARNG
      Microsoft Primitive Provider
    アルゴリズム名 = DUALECRNG
      Microsoft Primitive Provider

 

 

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


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