ホーム 主筆 その他ソフト その他情報 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:NULL暗号の実装(プログラム例)

2016年2月27日公開

NULL暗号を実装するアルゴリズムプロバイダについて、全体のプログラム例を示す。

プログラム例

アルゴリズムプロバイダとして機能するためには、下記の関数をエクスポートするDLLを作らなければならない。

// TestCAP.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。
//
 
#include "stdafx.h"
 
#include <bcrypt_provider.h>
#include <bcrypt.h>
 
// 下記は標準では定義されていないらしい
 
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS              ((NTSTATUS)0x00000000L)
#define STATUS_NOT_SUPPORTED        ((NTSTATUS)0xC00000BBL)
#define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
#define STATUS_HMAC_NOT_SUPPORTED   ((NTSTATUS)0xC000A001L)
#define STATUS_BUFFER_TOO_SMALL     ((NTSTATUS)0xC0000023L)
#define STATUS_NOT_IMPLEMENTED      ((NTSTATUS)0xC0000002L)
#endif
 
///////////////////////////////////////////////////////////////////////////////
// グローバル変数
 
 
HINSTANCE g_hInstance = NULL;
 
// CNGに公開する関数のアドレスを保持するテーブル
BCRYPT_CIPHER_FUNCTION_TABLE SymmCipherFunctionTable;
 
// アルゴリズムプロバイダのハンドルを返す
NTSTATUS WINAPI SymmOpenCipherProvider(
  __out BCRYPT_ALG_HANDLE *phAlgorithm,
  __in LPCWSTR pszAlgId,
  __in DWORD dwFlags
)
{
  // 挙動を変えるフラグを実装する要件はない
  UNREFERENCED_PARAMETER( dwFlags );
 
  // NULLが指定されたらハンドルを返せない
  if ( NULL == phAlgorithm )
    return STATUS_UNSUCCESSFUL;
 
  // "NULL"暗号をサポートする
  if( wcscmp( _T( "TestCAP-NULL" ), pszAlgId ) != 0 )
    return STATUS_NOT_SUPPORTED;
 
  // しいて確保すべきメモリ領域はないのだが、
  // とりあえず何かやっておく
  (*phAlgorithm) = malloc( 4 );
  if ( NULL == (*phAlgorithm) ) {
    return STATUS_UNSUCCESSFUL;
  }
  *(DWORD*)(*phAlgorithm) = 0x01020304;
 
  return STATUS_SUCCESS;
}
 
// アルゴリズムプロバイダのハンドルを開放する
NTSTATUS WINAPI SymmCloseCipherProvider(
  __inout BCRYPT_ALG_HANDLE hAlgorithm,
  __in DWORD dwFlags
)
{
  // 挙動を変えるフラグを実装する要件はない
  UNREFERENCED_PARAMETER( dwFlags );
 
  // 確保したメモリ領域を解放する
  free( hAlgorithm );
 
  return STATUS_SUCCESS;
}
 
// プロパティ値の取得
NTSTATUS WINAPI SymmGetCipherProperty(
  __in BCRYPT_HANDLE hObject,
  __in LPCWSTR pszProperty,
  __out_bcount_part_opt( cbOutput, *pcbResult ) PUCHAR pbOutput,
  __in ULONG cbOutput,
  __out ULONG *pcbResult,
  __in ULONG dwFlags
)
{
  UNREFERENCED_PARAMETER( hObject );
  UNREFERENCED_PARAMETER( dwFlags );
 
  // NULLが指定されたらデータ長が返せない
  if ( NULL == pcbResult )
    return STATUS_UNSUCCESSFUL;
 
  // オブジェクト長の取得
  // 明示的にオブジェクト長の取得が行われなくても、
  // CNGから勝手に呼び出されるため何らかのサポートが必要になる。
  if ( !_tcscmp( pszProperty, BCRYPT_OBJECT_LENGTH ) ) {
    // 必要になるバッファ長を設定する
    (*pcbResult) = sizeof( DWORD );
 
    // NULLが指定されていたらデータそのものを返す必要がない
    if ( NULL == pbOutput )
      return STATUS_SUCCESS;
 
    // バッファが足りない場合は失敗
    if ( cbOutput < (*pcbResult) )
      return STATUS_BUFFER_TOO_SMALL;
 
    // オブジェクトなんかいらんが、
    // とりあえず4を返しておく。根拠はない
    *( (DWORD*)pbOutput ) = 4;
 
    return STATUS_SUCCESS;
  }
 
  // 別に指定できるようなプロパティなどない
  return STATUS_NOT_IMPLEMENTED;
}
 
// プロパティ値の設定
NTSTATUS WINAPI SymmSetCipherProperty(
  __inout BCRYPT_HANDLE hObject,
  __in LPCWSTR pszProperty,
  __in_bcount( cbInput ) PUCHAR pbInput,
  __in ULONG cbInput,
  __in ULONG dwFlags
)
{
  UNREFERENCED_PARAMETER( hObject );
  UNREFERENCED_PARAMETER( pszProperty );
  UNREFERENCED_PARAMETER( pbInput );
  UNREFERENCED_PARAMETER( cbInput );
  UNREFERENCED_PARAMETER( dwFlags );
 
  // 別に指定できるようなプロパティなどない
  return STATUS_NOT_IMPLEMENTED;
}
 
// キーの生成
NTSTATUS WINAPI SymmGenerateKey(
  __inout BCRYPT_ALG_HANDLE hAlgorithm,
  __out BCRYPT_KEY_HANDLE *phKey,
  __out_bcount_full( cbKeyObject ) PUCHAR pbKeyObject,
  __in ULONG cbKeyObject,
  __in_bcount( cbSecret ) PUCHAR pbSecret,
  __in ULONG cbSecret,
  __in ULONG dwFlags
)
{
  UNREFERENCED_PARAMETER( dwFlags );
 
  // 使いはしないが、一応ハンドルの値を確認する
  if ( NULL == hAlgorithm )
    return STATUS_UNSUCCESSFUL;
 
  // NULLが指定されたらハンドルが返せない
  if ( NULL == phKey )
    return STATUS_UNSUCCESSFUL;
 
  // 意味はないが、何かを返しておく
  (*phKey) = malloc( 4 );
  if ( NULL == (*phKey) )
    return STATUS_UNSUCCESSFUL;
 
  // 生成すべきキーなどない
  return STATUS_SUCCESS;
}
 
// 暗号化する
NTSTATUS WINAPI SymmEncrypt(
  __inout BCRYPT_KEY_HANDLE hKey,
  __in_bcount( cbInput ) PUCHAR pbInput,
  __in ULONG cbInput,
  __in_opt VOID *pPaddingInfo,
  __inout_bcount_opt( cbIV ) PUCHAR pbIV,
  __in ULONG cbIV,
  __out_bcount_part_opt( cbOutput, *pcbResult ) PUCHAR pbOutput,
  __in ULONG cbOutput,
  __out ULONG *pcbResult,
  __in ULONG dwFlags
)
{
  // 挙動を変えるフラグを実装する要件はない
  UNREFERENCED_PARAMETER( dwFlags );
 
  // どうせ使いはしないのだが、一応ハンドルの値を確認する
  if ( NULL == hKey )
    return STATUS_UNSUCCESSFUL;
 
  // 入力のバッファは必要
  if ( NULL == pbInput )
    return STATUS_UNSUCCESSFUL;
 
  // パディングはサポートしないのでNULLでなければならないものとする
  if ( NULL != pPaddingInfo )
    return STATUS_UNSUCCESSFUL;
 
  // イニシャルベクタも使用しないので、
  // NULLでなければならないものとする
  if ( NULL != pbIV || cbIV > 0 )
    return STATUS_UNSUCCESSFUL;
 
  // 出力のバッファ長が0より大きいのに出力バッファが
  // 指定されていない場合はエラーとする
  if ( cbOutput > 0 && NULL == pbOutput )
    return STATUS_UNSUCCESSFUL;
 
  // 出力のバッファが指定されており、
  // かつバッファ長が不足する場合はエラーとする
  if ( cbOutput > 0 && cbOutput < cbInput )
    return STATUS_BUFFER_TOO_SMALL;
 
  // 出力バッファが指定されている場合は値をコピーする
  if ( NULL != pbOutput )
    memmove_s( pbOutput, cbOutput, pbInput, cbInput );
 
  // pcbResultが指定されている場合は、出力するバイト数を設定する
  if ( NULL != pcbResult )
    (*pcbResult) = cbInput;
 
  return STATUS_SUCCESS;
}
 
// 復号する
NTSTATUS WINAPI SymmDecrypt(
  __inout BCRYPT_KEY_HANDLE hKey,
  __in_bcount(cbInput) PUCHAR pbInput,
  __in ULONG cbInput,
  __in_opt VOID *pPaddingInfo,
  __inout_bcount_opt( cbIV ) PUCHAR pbIV,
  __in ULONG cbIV,
  __out_bcount_part_opt( cbOutput, *pcbResult ) PUCHAR pbOutput,
  __in ULONG cbOutput,
  __out ULONG *pcbResult,
  __in ULONG dwFlags
)
{
  // 挙動を変えるフラグを実装する要件はない
  UNREFERENCED_PARAMETER( dwFlags );
 
  // どうせ使いはしないのだが、一応ハンドルの値を確認する
  if ( NULL == hKey )
    return STATUS_UNSUCCESSFUL;
 
  // 入力のバッファは必要
  if ( NULL == pbInput )
    return STATUS_UNSUCCESSFUL;
 
  // パディングはサポートしないのでNULLでなければならないものとする
  if ( NULL != pPaddingInfo )
    return STATUS_UNSUCCESSFUL;
 
  // イニシャルベクタも使用しないので、NULLでなければならないものとする
  if ( NULL != pbIV || cbIV > 0 )
    return STATUS_UNSUCCESSFUL;
 
  // 出力のバッファ長が0より大きいのに出力バッファが
  // 指定されていない場合はエラーとする
  if ( cbOutput > 0 && NULL == pbOutput )
    return STATUS_UNSUCCESSFUL;
 
  // 出力のバッファが指定されており、
  // かつバッファ長が不足する場合はエラーとする
  if ( cbOutput > 0 && cbOutput < cbInput )
    return STATUS_BUFFER_TOO_SMALL;
 
  // 出力バッファが指定されている場合は値をコピーする
  if ( NULL != pbOutput )
    memmove_s( pbOutput, cbOutput, pbInput, cbInput );
 
  // pcbResultが指定されている場合は、出力するバイト数を設定する
  if ( NULL != pcbResult )
    (*pcbResult) = cbInput;
 
  return STATUS_SUCCESS;
}
 
// 鍵をインポートする
NTSTATUS WINAPI SymmImportKey(
  __in BCRYPT_ALG_HANDLE hAlgorithm,
  __in_opt BCRYPT_KEY_HANDLE hImportKey,
  __in LPCWSTR pszBlobType,
  __out BCRYPT_KEY_HANDLE *phKey,
  __out_bcount_full( cbKeyObject ) PUCHAR pbKeyObject,
  __in ULONG cbKeyObject,
  __in_bcount( cbInput ) PUCHAR pbInput,
  __in ULONG cbInput,
  __in ULONG dwFlags
)
{
  UNREFERENCED_PARAMETER( hAlgorithm );
  UNREFERENCED_PARAMETER( hImportKey );
  UNREFERENCED_PARAMETER( pszBlobType );
  UNREFERENCED_PARAMETER( phKey );
  UNREFERENCED_PARAMETER( pbKeyObject );
  UNREFERENCED_PARAMETER( cbKeyObject );
  UNREFERENCED_PARAMETER( pbInput );
  UNREFERENCED_PARAMETER( cbInput );
  UNREFERENCED_PARAMETER( dwFlags );
 
  // エクスポートすべきキーなどない
  return STATUS_NOT_IMPLEMENTED;
}
 
// 鍵をエクスポートする
NTSTATUS WINAPI SymmExportKey(
  __in BCRYPT_KEY_HANDLE hKey,
  __in_opt BCRYPT_KEY_HANDLE hExportKey,
  __in LPCWSTR pszBlobType,
  __out_bcount_part_opt( cbOutput, *pcbResult ) PUCHAR pbOutput,
  __in ULONG cbOutput,
  __out ULONG *pcbResult,
  __in ULONG dwFlags
)
{
  UNREFERENCED_PARAMETER( hKey );
  UNREFERENCED_PARAMETER( hExportKey );
  UNREFERENCED_PARAMETER( pszBlobType );
  UNREFERENCED_PARAMETER( pbOutput );
  UNREFERENCED_PARAMETER( cbOutput );
  UNREFERENCED_PARAMETER( pcbResult );
  UNREFERENCED_PARAMETER( dwFlags );
 
  // インポートすべきキーなどない
  return STATUS_NOT_IMPLEMENTED;
}
 
// 鍵を複製する
NTSTATUS WINAPI SymmDuplicateKey(
  __in BCRYPT_KEY_HANDLE hKey,
  __out BCRYPT_KEY_HANDLE *phNewKey,
  __out_bcount_full( cbKeyObject ) PUCHAR pbKeyObject,
  __in ULONG cbKeyObject,
  __in ULONG dwFlags
)
{
  UNREFERENCED_PARAMETER( hKey );
  UNREFERENCED_PARAMETER( phNewKey );
  UNREFERENCED_PARAMETER( pbKeyObject );
  UNREFERENCED_PARAMETER( cbKeyObject );
  UNREFERENCED_PARAMETER( dwFlags );
 
  // 複製すべきキーなどない
  return STATUS_NOT_IMPLEMENTED;
}
 
// 鍵を破棄する
NTSTATUS WINAPI SymmDestroyKey(
  __inout BCRYPT_KEY_HANDLE hKey
)
{
  free( hKey );
 
  return STATUS_SUCCESS;
}
 
// インタフェースとなる関数のアドレスを応答する
NTSTATUS WINAPI GetCipherInterface(
  __in LPWSTR pszProviderName,
  __in LPWSTR pszAlgId,
  __out BCRYPT_CIPHER_FUNCTION_TABLE **ppFunctionTable,
  __in DWORD dwFlags
)
{
  NTSTATUS Status = STATUS_NOT_SUPPORTED;
 
  // プロバイダ名によって挙動を変える要件はない
  UNREFERENCED_PARAMETER( pszProviderName );
 
  // 別に挙動を変えるようなフラグを実装する用件はない
  UNREFERENCED_PARAMETER( dwFlags );
 
  // 関数ポインタを格納した構造体を準備して、そのアドレスを返す
  BCRYPT_CIPHER_FUNCTION_TABLE work = {
    BCRYPT_CIPHER_INTERFACE_VERSION_1,
    SymmOpenCipherProvider,
    SymmGetCipherProperty,
    SymmSetCipherProperty,
    SymmCloseCipherProvider,
    SymmGenerateKey,
    SymmEncrypt,
    SymmDecrypt,
    SymmImportKey,
    SymmExportKey,
    SymmDuplicateKey,
    SymmDestroyKey
  };
  SymmCipherFunctionTable = work;
 
  // "NULL"暗号をサポートする
  if( wcscmp( _T( "TestCAP-NULL" ), pszAlgId ) == 0 ) {
    (*ppFunctionTable) = &SymmCipherFunctionTable;
    Status = STATUS_SUCCESS;
  }
 
  return Status;
}

<< 「CNG:NULL暗号の実装」に戻る

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


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