Windows環境で AES と SHA256 を CryptAPI で使用したくなり、調べ始めました。
.NET Framework で簡単にできることも CryptAPI 単独で実現しようとすると手続きが面倒です。でも時々Win32で実現する必要がある場合もあるので、まぁ情報として有意義ではないかと思いますのでこちらで情報発信させていただきます。
win32 の CryptAPI を使って AES 暗号を実装そうしてみます、
コンパイラ : | Visual Studio 2008 sp1 | |
OS : | Windows7 64bit Professional | |
[プログラムソース "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
#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
#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;
}
}
<?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 ライセンスで提供されます。
2023-05-02 | - | ページデザイン更新 |
2012-01-28 | - | 新規作成 |