AES (CryptAPI)

Windows環境で AES と SHA256 を CryptAPI で使用したくなり、調べ始めました。
.NET Framework で簡単にできることも CryptAPI 単独で実現しようとすると手続きが面倒です。でも時々Win32で実現する必要がある場合もあるので、まぁ情報として有意義ではないかと思いますのでこちらで情報発信させていただきます。

 

 

 

1. CryptAPI で AES 暗号を使ってみる

[概要]

win32 の CryptAPI を使って AES 暗号を実装そうしてみます、

 

[環境]

コンパイラ : Visual Studio 2008 sp1  
OS : Windows7 64bit Professional  

 

 

サンプルプログラム一式 ダウンロード(zip形式)

 

[プログラムソース "aes.h"]
namespace aes_library {

enum AES_ERROR_CODE {
    NORMAL                    = 0,
    INVALID_ALGORITHM         = 100,
    INVALID_ARGUMENT,
    INVALID_KEY_LENGTH,
    LOGIC_ERROR
};

const size_t AES_KEY_SIZE = 16 ;

bool createAesKey( std::string passFraise, unsigned char (&aesKey)[AES_KEY_SIZE],  AES_ERROR_CODE &errorCode );
bool encryptData( unsigned char* rawData, size_t sizeRawData, unsigned char (&keyData)[AES_KEY_SIZE], unsigned char* cryptData, size_t sizeCryptData, size_t &cryptDataBytes, AES_ERROR_CODE &errorCode );
bool decryptData( unsigned char* cryptData, size_t sizeCryptData, unsigned char (&keyData)[AES_KEY_SIZE], unsigned char* rawData, size_t sizeRawData, size_t &rawDataBytes, AES_ERROR_CODE &errorCode );

} // namespace aes_library
 
[プログラムソース "aes.cpp"]
#include <windows.h>
#include <iostream>
#include <cassert>

#include "Aes.h"


using namespace std;


namespace aes_library {


/*=====================================================================*/
//! AES 128ビット用の鍵データを作成
/*!
    AES 128ビット用の鍵データを作成します。16バイトデータです。
    生成アルゴリズムは以下の通りです。
    -# ハッシュアルゴリズム SHA256 により passFraise のダイジェスト32バイトデータを生成します。
    -# ダイジェスト32バイト の偶数バイト{0,2,4,・・・,30}を連結した16バイトデータを生成、これをAES鍵データとして出力します。

    @param[in]      passFraise      暗号化対象の平分データ
    @param[out]     aesKey          AES128ビット用16バイト鍵
    @param[out]     errorCode       エラーコード
    @retval         true            正常終了
    @retval         false           異常終了
    @note           Windows Vista 以降でのみ動作します。
                    Windows XP では CALG_SHA_256、CALG_SHA_384、CALG_SHA_512 は動作しません。
    @author         木下英俊
    @date           2011-12-04 新規作成
*/
/*=====================================================================*/
bool createAesKey( std::string passFraise, unsigned char (&aesKey)[AES_KEY_SIZE],  AES_ERROR_CODE &errorCode )
{
    bool    bRet = true ;

    // キーコンテナーの取得
    BOOL        bResult = TRUE ;
    HCRYPTPROV  hProv = NULL ;
    HCRYPTHASH  hHash = NULL ;


    /*========*/
    /* 前処理 */
    /*========*/
    errorCode = NORMAL ;

    /*========*/
    /* 処理部 */
    /*========*/
    while( bRet == true ){
        const ALG_ID AlgId      = CALG_SHA_256 ;
        const size_t SizeHash   = 32 ;


        // CPSハンドル取得
        {
            bResult = CryptAcquireContext(
                        &hProv,                 // ハンドルが戻ります
                        NULL,                   // 既定のユーザーのCSPを使います
                        MS_ENH_RSA_AES_PROV,    // バンドルされたMicrosoftのCSPを指定
                        PROV_RSA_AES,           // タイプを指定
                        0);                     // キーコンテナーがある場合の指定です
            if ( !bResult ){
                if (!CryptAcquireContext( &hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET)){
                    cerr << "CryptAcquireContext error" << endl;
                    errorCode = LOGIC_ERROR ;
                    bRet = false ;
                    break ;
                }
            }
        }

        // ハッシュ計算インスタンスハンドル生成
        {
            bResult = CryptCreateHash(
                            hProv,              // ハッシュ値を計算するCSPのハンドル
                            AlgId,              // ハッシュ値の計算アルゴリズム
                            0,                  // (後述します)
                            0,                  //  未使用、0(ゼロ)をセット
                            &hHash);            //  求めるインスタンスのハンドル
            if (!bResult){
                cerr << "CryptCreateHash error" << endl;
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }
        }

        // ハッシュ計算
        {
            bResult = CryptHashData(
                            hHash,                      // ハッシュ計算インスタンスのハンドル
                            (BYTE*)passFraise.c_str(),  // 実際のパスワードを指定
                            (DWORD)passFraise.size(),   // パスワードのバイト長
                            0);                         // 0 指定
            if (!bResult){
                cerr << "CryptHashData error" << endl;
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }
        }

        // ハッシュ値計算 & AES用鍵データ作成
        {
            DWORD   dwHashSize = 0 ;
            unsigned char hashResult[SizeHash] ;

            // ハッシュサイズ確認;dwHashSize(32)バイト以外ならNG
            bResult = CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwHashSize, 0);
            if (!bResult){
                cerr << "CryptGetHashParam error" << endl;
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }

            // 生成されるハッシュサイズ(dwHashSize)が期待している値(SizeHash)と異なる場合は異常とする
            if ( dwHashSize != SizeHash ){
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }

            // ハッシュ値 取得
            bResult = CryptGetHashParam( hHash, HP_HASHVAL, (BYTE*)hashResult, &dwHashSize, 0 );
            if (!bResult){
                cerr << "CryptGetHashParam error" << endl;
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }

            // ハッシュ値からAES用鍵データ作成
            // ハッシュ結果の偶数バイトを連結して鍵とする
            assert( AES_KEY_SIZE*2 <= SizeHash );
            for ( size_t i=0; i<AES_KEY_SIZE; ++i ){
                aesKey[i] = hashResult[i*2] ;
            }
        }

        /**/
        break ;
    }


    /*========*/
    /* 後処理 */
    /*========*/
    // ハッシュ インスタンス 解放
    if ( hHash != NULL ){
        bResult = CryptDestroyHash(hHash);
        if (!bResult){
            cerr << "CryptDestroyHash error" << endl;
            errorCode = LOGIC_ERROR ;
            bRet = false ;
        }
    }

    // CPSハンドル解放
    if ( hProv != NULL ){
        bResult = CryptReleaseContext(hProv, 0);
        if (!bResult){
            cerr << "CryptReleaseContext error" << endl;
            errorCode = LOGIC_ERROR ;
            bRet = false ;
        }
    }

    return bRet ;

}



namespace {

    /*=====================================================================*/
    //! 暗号処理 初期化
    /*!
        CryptAPI を使用した暗号処理の初期化処理を行います。
        暗号アルゴリズムなどは以下の方式で設定します。
        - アルゴリズム:AES
        - 鍵長:128ビット
        - モード:CBCモード
        - イニシャルベクタ(IV):0
        - パディング方式:PKCS7 (コード上ではPKCS5と記載していますがPKCS7と同義です。)
        
        @param[out]     hProv           CPSハンドル
        @param[out]     hKey            鍵ハンドル
        @param[in]      keyData         暗号鍵データ。データサイズは AES_KEY_SIZE 。
        @param[out]     errorCode       エラーコード
        @retval         true            正常終了
        @retval         false           異常終了
        @author         木下英俊
        @date           2011-12-04 新規作成
    */
    /*=====================================================================*/
    bool InitializeAes( HCRYPTPROV &hProv, HCRYPTKEY &hKey, unsigned char (&keyData)[AES_KEY_SIZE], AES_ERROR_CODE &errorCode )
    {
        bool bRet = true ;


        /*========*/
        /* 前処理 */
        /*========*/

        errorCode = NORMAL ;


        /*========*/
        /* 処理部 */
        /*========*/

        while( bRet == true ){
            BOOL bResult = TRUE ;

            /* CPSハンドル取得(暗号処理 初期化) */
            {
                bResult = CryptAcquireContext(
                            &hProv,                 // ハンドルが戻ります
                            NULL,                   // 既定のユーザーのCSPを使います
                            MS_ENH_RSA_AES_PROV,    // バンドルされたMicrosoftのCSPを指定
                                                    // XP では MS_ENH_RSA_AES_PROV_XP を指定のこと
                            PROV_RSA_AES,           // タイプを指定
                            0);                     // キーコンテナーがある場合の指定です
                if ( !bResult ){
                    if (!CryptAcquireContext( &hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET)){
                        cerr << "CryptAcquireContext error" << endl;
                        errorCode = LOGIC_ERROR ;
                        bRet = false ;
                        break ;
                    }
                }
            }


            /* 暗号アルゴリズム、鍵情報 設定 */
            {
                struct KeyBLOB{
                    BLOBHEADER hdr;
                    DWORD cbKeySize;
                    BYTE rgbKeyData[AES_KEY_SIZE]; // 16:AES_128のキー長
                };

                KeyBLOB kb;

                kb.hdr.bType    = PLAINTEXTKEYBLOB;
                kb.hdr.bVersion = CUR_BLOB_VERSION;
                kb.hdr.reserved = 0;
                kb.hdr.aiKeyAlg = CALG_AES_128;     // AES_128
                kb.cbKeySize    = AES_KEY_SIZE;     // AES_KEY_SIZE = 16

                memcpy( kb.rgbKeyData, keyData, AES_KEY_SIZE );
                
                bResult = CryptImportKey(hProv,(BYTE*)&kb, sizeof(kb), 0, 0, &hKey); // キー作成
                if ( !bResult ){
                    errorCode = LOGIC_ERROR ;
                    bRet = false ;
                    break ;
                }       
            }


            /* 暗号モード設定(CBCモード) */
            {
                DWORD   mode = CRYPT_MODE_CBC;

                if (!CryptSetKeyParam( hKey, KP_MODE, (BYTE*)&mode, 0 )){
                    errorCode = LOGIC_ERROR ;
                    bRet = false ;
                    break ;
                }
            }

            /* IV(イニシャルベクタ)設定 */
            {
                BYTE    iv[AES_KEY_SIZE] ;
                
                for ( size_t i=0; i<AES_KEY_SIZE; ++i ){
                    iv[i] = 0 ;
                }
                
                if ( !CryptSetKeyParam( hKey, KP_IV, iv, 0)){
                    errorCode = LOGIC_ERROR ;
                    bRet = false ;
                    break ;
                }
            }

            /* パディングモード設定 */
            {
                DWORD      padding_mode = PKCS5_PADDING;
                
                if (!CryptSetKeyParam( hKey, KP_PADDING, (BYTE*)&padding_mode, 0)){
                    errorCode = LOGIC_ERROR ;
                    bRet = false ;
                    break ;
                }
            }

            /* */
            break ;
        }



        /*========*/
        /* 後処理 */
        /*========*/
        return bRet ;
    }



    /*=====================================================================*/
    //! 暗号処理 解放処理
    /*!
        CryptAPI を使用した暗号処理の解放処理を行います。
        
        @param[in]      hProv           CPSハンドル。InitializeAes で使用したハンドルを指定してください。                                       
        @param[in]      hKey            鍵ハンドル。InitializeAes で使用したハンドルを指定してください。
        @param[out]     errorCode       エラーコード
        @retval         true            正常終了
        @retval         false           異常終了
        @author         木下英俊
        @date           2011-12-04 新規作成
    */
    /*=====================================================================*/
    bool DisposeAes( HCRYPTPROV &hProv, HCRYPTKEY &hKey, AES_ERROR_CODE &errorCode )
    {
        bool bRet = true ;

        /*========*/
        /* 前処理 */
        /*========*/
        errorCode = NORMAL ;

        /*========*/
        /* 処理部 */
        /*========*/
        // 鍵ハンドル解放
        if ( hKey != NULL ){
            if (!CryptDestroyKey(hKey)){
                cerr << "CryptDestroyKey error" << endl;
                errorCode = LOGIC_ERROR ;
                bRet = false ;
            }
        }

        // CPSハンドル解放
        if ( hProv != NULL ){
            if (!CryptReleaseContext(hProv, 0)){
                cerr << "CryptReleaseContext error" << endl;
                errorCode = LOGIC_ERROR ;
                bRet = false ;
            }
        }

        return bRet ;
    }
}



/*=====================================================================*/
//! データを暗号化する
/*!
    データを暗号化します。
    暗号アルゴリズムなど詳細は関数 InitializeAes の説明を参照してください。
    
    @param[in]      rawData         暗号化対象の平分データ
    @param[in]      sizeRawData     rawData の有効データサイズ
    @param[in]      keyData         暗号鍵データ。データサイズは AES_KEY_SIZE 。
    @param[out]     cryptData       暗号化データ格納領域
                                    本関数をコールする前に呼び出し側でメモリ確保しておいてください。
                                    必要とするデータサイズに関する説明は sizeCryptData の説明を参照してください。
    @param[in]      sizeCryptData   cryptData の有効バッファサイズ。
                                    以下の関係を満足しない場合、本関数はエラーになります。エラーコードは INVALID_ARGUMENT を応答します。
                                    @code
                                    sizeCryptData >= ((sizeRawData+16)/16)*16 ;
                                    @endcode
    @param[out]     cryptDataBytes  暗号化データサイズ
    @param[out]     errorCode       エラーコード
    @retval         true            正常終了
    @retval         false           異常終了
    @author         木下英俊
    @date           2011-12-04 新規作成
*/
/*=====================================================================*/
bool encryptData( unsigned char* rawData, size_t sizeRawData, unsigned char (&keyData)[AES_KEY_SIZE], unsigned char* cryptData, size_t sizeCryptData, size_t &cryptDataBytes, AES_ERROR_CODE &errorCode )
{
    bool    bRet = true ;

    // キーコンテナーの取得
    HCRYPTPROV  hProv = NULL ;
    HCRYPTKEY   hKey = NULL ;


    /*========*/
    /* 前処理 */
    /*========*/
    errorCode = NORMAL ;

    // 出力バッファサイズのチェック
    if ( sizeCryptData < (((sizeRawData+16)/16)*16)){

        // 暗号データ出力領域不足
        cerr << "[ERROR] cryptData output memory is not enough." << endl;
        bRet = false ;
        errorCode = INVALID_ARGUMENT ;
    }
    // cryptData のNULLチェック
    if ( cryptData == NULL ){
        cerr << "[ERROR] cryptData must be memory allocated." << endl;
        bRet = false ;
        errorCode = INVALID_ARGUMENT ;
    }
    // rawData のNULLチェック
    if ( rawData == NULL ){
        cerr << "[ERROR] rawData must be memory allocated." << endl;
        bRet = false ;
        errorCode = INVALID_ARGUMENT ;
    }


    /*========*/
    /* 処理部 */
    /*========*/
    while( bRet == true ){

        /* 初期処理 */
        if ( !InitializeAes( hProv, hKey, keyData, errorCode ) ){
            bRet = false ;
            break ;
        }

        /* 暗号化 */
        {
            DWORD       sizeData_ = sizeRawData ;

            // 平分データを cryptData へコピー。cryptData が入力と出力を兼ねるAPI仕様のため
            memcpy( cryptData, rawData, sizeRawData );

            //
            cryptDataBytes = 0 ;

            // 暗号化
            if(!CryptEncrypt(
                    hKey,                       // 鍵のハンドル
                    0,                          // 暗号化と同時にハッシュ化する場合に指定
                    TRUE,                       // 最後のデータを渡すときに真
                    0,                          // ゼロを指定
                    cryptData,                  // 暗号化されるデータのポインター
                    &sizeData_,                 // 暗号化データのバイト長データの格納ポインター, 演算後は暗号化された結果のデータサイズを格納
                    (DWORD)sizeCryptData))      // データバッファーの大きさ
            {
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }

            // 暗号化された結果のデータサイズを出力変数へコピー
            cryptDataBytes = sizeData_ ;
        }

        /**/
        break ;
    }

    /*========*/
    /* 後処理 */
    /*========*/
    if ( !DisposeAes( hProv, hKey, errorCode ) ){
        bRet = false ;
    }

    return bRet ;
}



/*=====================================================================*/
//! データを復号化する
/*!
    データを復号化します。
    暗号アルゴリズムなど詳細は関数 InitializeAes の説明を参照してください。
    
    @param[in]      cryptData       暗号データ
    @param[in]      sizeCryptData   cryptData のデータサイズ
    @param[in]      keyData         暗号鍵データ。データサイズは AES_KEY_SIZE 。
    @param[out]     rawData         復号化データ格納領域
                                    本関数をコールする前に呼び出し側でメモリ確保しておいてください。
                                    必要とするデータサイズに関する説明は sizeRawData の説明を参照してください。
    @param[in]      sizeRawstData   rawData の有効バッファサイズ。
                                    以下の関係を満足しない場合、本関数はエラーになります。エラーコードは INVALID_ARGUMENT を応答します。
                                    @code
                                    sizeRawData >= sizeCryptData ;
                                    @endcode
    @param[out]     rawDataBytes    復号化データサイズ
    @param[out]     errorCode       エラーコード
    @retval         true            正常終了
    @retval         false           異常終了
    @author         木下英俊
    @date           2011-12-04 新規作成
*/
/*=====================================================================*/
bool decryptData( unsigned char* cryptData, size_t sizeCryptData, unsigned char (&keyData)[AES_KEY_SIZE], unsigned char* rawData, size_t sizeRawData, size_t &rawDataBytes, AES_ERROR_CODE &errorCode )
{
    bool    bRet = true ;

    // キーコンテナーの取得
    HCRYPTPROV  hProv = NULL ;
    HCRYPTKEY   hKey = NULL ;


    /*========*/
    /* 前処理 */
    /*========*/
    errorCode = NORMAL ;

    // 出力バッファサイズのチェック
    if ( sizeRawData < sizeCryptData ){
        // 復号化データ出力領域不足
        cerr << "[ERROR] rawData output memory is not enough." << endl;
        bRet = false ;
        errorCode = INVALID_ARGUMENT ;
    }
    // cryptData のNULLチェック
    if ( cryptData == NULL ){
        cerr << "[ERROR] cryptData must be memory allocated." << endl;
        bRet = false ;
        errorCode = INVALID_ARGUMENT ;
    }
    // rawData のNULLチェック
    if ( rawData == NULL ){
        cerr << "[ERROR] rawData must be memory allocated." << endl;
        bRet = false ;
        errorCode = INVALID_ARGUMENT ;
    }


    /*========*/
    /* 処理部 */
    /*========*/
    while( bRet == true ){

        /* 初期処理 */
        if ( !InitializeAes( hProv, hKey, keyData, errorCode ) ){
            bRet = false ;
            break ;
        }

        /* 復号化 */
        {
            DWORD       sizeData_ = sizeCryptData ;

            // 暗号データを rawData へコピー。rawData が入力と出力を兼ねるAPI仕様のため
            memcpy( rawData, cryptData, sizeCryptData );
            
            //
            rawDataBytes = 0 ;

            // 復号化
            if(!CryptDecrypt(
                    hKey,                       // 鍵のハンドル
                    0,                          // 復号化と同時にハッシュ化する場合に指定
                    TRUE,                       // 最後のデータを渡すときに真
                    0,                          // ゼロを指定
                    rawData,                    // 復号化されるデータのポインター
                    &sizeData_))                // 暗号データのバイト長データの格納ポインター, 演算後は復号化された結果のデータサイズを格納
            {
                errorCode = LOGIC_ERROR ;
                bRet = false ;
                break ;
            }

            // 復号化された結果のデータサイズを出力変数へコピー
            rawDataBytes = sizeData_ ;
        }

        /**/
        break ;
    }


    /*========*/
    /* 後処理 */
    /*========*/
    if ( !DisposeAes( hProv, hKey, errorCode ) ){
        bRet = false ;
    }

    return bRet ;
}


} // namespace aes_library
		

[プログラムソース "test_aes.cpp"]
#include "stdafx.h"

#include "Aes.h"


using namespace std;
using namespace boost::property_tree;

using namespace aes_library;



int _tmain(int argc, _TCHAR* argv[])
{
    bool            bRet = true ;

    // 平文データ
    unsigned char   rawData[] = {00, 01, 02, 03};
    size_t          sizeRawData = sizeof(rawData)/sizeof(rawData[0]);

    // 暗号データ
    unsigned char*  cryptData = NULL ;
    size_t          sizeCryptData = 0 ;             // crpyptData のバッファサイズ
    size_t          cryptDataBytes = 0 ;            // 暗号化された結果のデータサイズ

    // 暗号データから復号された平文データ
    unsigned char*  rawData2 = NULL ;
    size_t          sizeRawData2 = 0 ;              // rawData2 のバッファサイズ
    size_t          rawData2Bytes = 0 ;             // 復号化された結果のデータサイズ

    // 鍵情報
    string          strPassFraise = "";             // パスフレーズ
    unsigned char   aesKey[AES_KEY_SIZE];           // AES演算用鍵データ
    
    // エラーコード
    AES_ERROR_CODE  errorCode ;


    /*========*/
    /* 前処理 */
    /*========*/
    UNREFERENCED_PARAMETER(argc);           // UNREFERENCED_PARAMETER は WinNT.h で定義されています。
    UNREFERENCED_PARAMETER(argv);           // UNREFERENCED_PARAMETER は WinNT.h で定義されています。


    /*========*/
    /* 処理部 */
    /*========*/
    while(bRet) {

        /*==================================================*/
        /* configuration.xml ファイルからパスフレーズを取得 */
        /*==================================================*/
        /*
            NOTE:
            XMLファイルの読み取りに boostライブラリ(Ver. 1.47) の property_tree を使用しています。
            property_tree は boostライブラリの1.41以降から使用できます。
            boostライブラリは以下のURLから取得してください。boostpro にあるインストーラを使用する方が楽に導入できます。
            http://www.boost.org/
            http://www.boostpro.com/download/
        */
        {
            const string filename = "configuration.xml";
            ptree pt;

            // XMLファイルを開く
            try{
                read_xml( filename, pt );
            }
            catch( xml_parser_error e ){
                // filename が無い場合の例外
                cerr << "[ERROR] Cannnot open file \"" << filename << "\"" << "." << endl;
                bRet = false ;
                break ;
            }

            // パスフレーズ読み取り
            if ( boost::optional str = pt.get_optional("Documents.DataFormat.Encryption.<xmlattr>.PassFraise") )
            {
                strPassFraise = str.get();
                cout << "Pass fraise : \"" << strPassFraise << "\"" << endl << endl;
            }
            else {
                // 属性 "Documents.DataFormat.Encryption.<xmlattr>.PassFraise" が無い場合の異常処理
                cerr << "[ERROR] \"Documents.DataFormat.Encryption.<xmlattr>.PassFraise\" is nothing." << std::endl;
                bRet = false ;
                break ;
            }
        }
        
        // strPassFraise から16バイトの鍵情報生成
        {
            AES_ERROR_CODE  errorCode = NORMAL ;

            if (!createAesKey( strPassFraise, aesKey, errorCode )){
                cerr << "[ERROR] createAesKey() is fail." << endl;
                bRet = false ;
                break ;
            }
        }

        // Encrypt
        {
            cout << "[Encrypt]" << endl;

            // 暗号化した結果を保存する領域を確保
            // 生データサイズ に1~16バイトを加えた数で、16の倍数になる値、が出力サイズ
            sizeCryptData = ((sizeRawData + 16)/16)*16 ;
            if ( cryptData != NULL ){
                delete[] cryptData ;
            }
            cryptData = new unsigned char[sizeCryptData];
            
            if ( !encryptData( rawData, sizeRawData, aesKey, cryptData, sizeCryptData, cryptDataBytes, errorCode ) ){
                cerr << "[ERROR] encryptData() is fail." << endl;
                bRet = false ;
                break ;
            }

            // 暗号化されたデータサイズのチェック
            assert( sizeCryptData == cryptDataBytes );
        }

        // 演算結果出力
        {
            cout << "Key         : ";
            for ( size_t i=0; i<AES_KEY_SIZE; ++i ){
                cout << hex << setw(2) << setfill('0') << (int)aesKey[i] << " ";
            }
            cout << endl;

            cout << "Raw data    : ";
            for ( size_t i=0; i<sizeRawData; ++i ){
                cout << hex << setw(2) << (int)rawData[i] << " ";
            }
            cout << endl;

            cout << "Crypt data  : ";
            for ( size_t i=0; i<cryptDataBytes; ++i ){
                cout << hex << setw(2) << (int)cryptData[i] << " ";
            }
            cout << endl;

            cout << endl;
        }


        // Decrypt
        {
            cout << "[Decrypt]" << endl;
            
            // 復号化した結果を保存する領域を確保
            sizeRawData2 = cryptDataBytes ;
            if ( rawData2 != NULL ){
                delete[] rawData2 ;
            }
            rawData2 = new unsigned char[sizeRawData2];
            
            if ( !decryptData( cryptData, cryptDataBytes, aesKey, rawData2, sizeRawData2, rawData2Bytes, errorCode ) ){
                cerr << "[ERROR] encryptData() is fail." << endl;
                bRet = false ;
                break ;
            }
        }

        // 演算結果出力
        {
            cout << "Key         : ";
            for ( size_t i=0; i<AES_KEY_SIZE; ++i ){
                cout << hex << setw(2) << setfill('0') << (int)aesKey[i] << " ";
            }
            cout << endl;

            cout << "Crypt data  : ";
            for ( size_t i=0; i<cryptDataBytes; ++i ){
                cout << hex << setw(2) << (int)cryptData[i] << " ";
            }
            cout << endl;

            cout << "Raw data    : ";
            for ( size_t i=0; i<rawData2Bytes; ++i ){
                cout << hex << setw(2) << (int)rawData2[i] << " ";
            }
            cout << endl;

            cout << endl;
        }


        // 演算結果確認
        {
            // データサイズ チェック
            assert( sizeRawData == rawData2Bytes );

            // データチェック
            for ( size_t i=0; i<sizeRawData; ++i ){
                assert( rawData[i] == rawData2[i] );
            }
        }

        /**/
        break ;
    }


    /*========*/
    /* 後処理 */
    /*========*/
    // リソース解放
    if ( cryptData != NULL ){
        delete[] cryptData ;
        cryptData = NULL ;
    }
    if ( rawData2 != NULL ){
        delete[] rawData2 ;
        rawData2 = NULL ;
    }

    // 処理結果出力
    {
        cout << "[Result] " ;
        if ( bRet ){
            cout << "OK" << endl;
        }
        else{
            cout << "!!! NG !!!" << endl;
        }
    }

    // [enter]キー押下待ち
    {
        string str ;
        cout << "HIT [enter] KEY !! " ;
        getline( cin, str );
        
    }

    // return
    if ( bRet ){
        return EXIT_SUCCESS;
    }
    else{
        return EXIT_FAILURE;
    }
}

[プログラムソース "configuration.xml"]
<?xml version="1.0" encoding="Shift_JIS"?>
<Documents>
  <DataFormat>
    <Encryption PassFraise="PassFraise"/>
  </DataFormat>
</Documents>

[実行結果]
Pass fraise : "PassFraise"

[Encrypt]
Key : 68 6d 26 2f 27 8c f6 99 53 20 55 8f 43 f7 11 0d
Raw data : 00 01 02 03
Crypt data : 72 0e bf e3 8b ff 8a f2 dc ba 09 b6 10 1d 6b ef

[Decrypt]
Key : 68 6d 26 2f 27 8c f6 99 53 20 55 8f 43 f7 11 0d
Crypt data : 72 0e bf e3 8b ff 8a f2 dc ba 09 b6 10 1d 6b ef
Raw data : 00 01 02 03

[Result] OK
HIT [enter] KEY !!

 

 

ライセンス

本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。

The MIT License (MIT)

  Copyright 2012 Kinoshita Hidetoshi

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 

 

参考

 


 

変更履歴

2023-05-02 - ページデザイン更新
2012-01-28 - 新規作成

 

Programming Items トップページ

プライバシーポリシー