CryptDecode関数の働き・役割
CryptDecode関数は、CryptEncode関数で暗号化されたデータを復号化するために使用されます。この関数は、指定された暗号化方式を使って、暗号化された配列から元のデータを逆変換します。CryptEncode関数で使用した暗号化キーと同じキーを使うことで、データを復号化し元の形に戻すことができます。
CryptDecode関数の引数について
CryptDecode関数の引数は、以下の通りです。
第1引数: method
methodは、暗号化および復号化の手法を指定します。これはENUM_CRYPT_METHOD列挙型の値の1つを指定します。たとえば、DES暗号化方式やAES 128ビット暗号化方式などがあります。
第2引数: data[]
dataは、暗号化されたソースデータを格納した配列です。この配列には、CryptEncode関数で暗号化されたバイトデータが含まれます。
第3引数: key[]
keyは、暗号化および復号化に使用するキーを格納した配列です。CryptEncode関数で使用したのと同じキーを指定する必要があります。暗号化方式によって、キーの長さやフォーマットが異なります。
第4引数: result[]
resultは、復号化されたデータを格納するための配列です。復号化された後、resultに元のデータが保存されます。この配列のサイズは、必要な容量に応じて適切に確保しておく必要があります。
CryptDecode関数の戻り値について
CryptDecode関数は、復号化されたデータのバイト数を整数として返します。成功した場合、復号化されたデータのサイズ(バイト数)が返されます。エラーが発生した場合は0が返され、エラーの詳細はGetLastError関数を使用して取得することができます。
例えば、復号化に失敗した場合には、原因を確認するためにGetLastError関数を呼び出すことが推奨されます。
CryptDecode関数を使ったサンプルコード
//+------------------------------------------------------------------+
//| ArrayToHex |
//| バイト配列を16進数形式の文字列に変換する関数 |
//+------------------------------------------------------------------+
string ArrayToHex(uchar &arr[], int count=-1)
{
string res=""; // 結果の文字列を初期化
//--- 配列サイズが適切かチェック
if(count<0 || count>ArraySize(arr))
count=ArraySize(arr); // カウントが不正の場合は配列のサイズに設定
//--- 配列を16進数文字列に変換
for(int i=0; i<count; i++)
res+=StringFormat("%.2X",arr[i]); // 各バイトを16進数形式で文字列に追加
//--- 結果の文字列を返す
return(res);
}
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数 |
//| OnStart関数は、スクリプト実行時に呼び出される自動的なエントリーポイントです |
//+------------------------------------------------------------------+
void OnStart()
{
string text="The quick brown fox jumps over the lazy dog"; // 暗号化する元のテキスト
string keystr="ABCDEFG"; // 暗号化に使用するキー
uchar src[], dst[], key[]; // データ配列(src: 元データ, dst: 暗号化されたデータ, key: 暗号化キー)
//--- キーを準備する(文字列をバイト配列に変換)
StringToCharArray(keystr, key);
//--- テキストをsrc配列に変換する(文字列をバイト配列にコピー)
StringToCharArray(text, src);
//--- 初期データの情報を出力する
PrintFormat("Initial data: size=%d, string='%s'", ArraySize(src), CharArrayToString(src));
// 配列サイズと文字列としての内容を出力
//--- src配列をkey配列を使ってDES 56ビットキーで暗号化
int res = CryptEncode(CRYPT_DES, src, key, dst);
// CRYPT_DES方式で暗号化を実行し、結果をdst配列に格納
//--- 暗号化処理が成功したか確認
if(res > 0)
{
//--- 暗号化されたデータを16進数形式で表示
PrintFormat("Encoded data: size=%d %s", res, ArrayToHex(dst));
// 暗号化後のデータサイズと16進数形式の内容を出力
//--- 暗号化されたdst配列をsrc配列にデコードする
res = CryptDecode(CRYPT_DES, dst, key, src);
// 同じキーとDES方式でデコードを実行
//--- デコードが成功したか確認
if(res > 0)
{
//--- デコードされたデータを表示
PrintFormat("Decoded data: size=%d, string='%s'", ArraySize(src), CharArrayToString(src));
// デコードされたデータのサイズと文字列を出力
}
else
Print("Error in CryptDecode. Error code=", GetLastError());
// デコードエラーが発生した場合のエラーメッセージを出力
}
else
Print("Error in CryptEncode. Error code=", GetLastError());
// 暗号化エラーが発生した場合のエラーメッセージを出力
}
サンプルコード解説1:ArrayToHex関数(オリジナル関数)
//+------------------------------------------------------------------+
//| ArrayToHex |
//| バイト配列を16進数形式の文字列に変換する関数 |
//+------------------------------------------------------------------+
string ArrayToHex(uchar &arr[], int count=-1)
{
string res=""; // 結果の文字列を初期化
//--- 配列サイズが適切かチェック
if(count<0 || count>ArraySize(arr))
count=ArraySize(arr); // カウントが不正の場合は配列のサイズに設定
//--- 配列を16進数文字列に変換
for(int i=0; i<count; i++)
res+=StringFormat("%.2X",arr[i]); // 各バイトを16進数形式で文字列に追加
//--- 結果の文字列を返す
return(res);
}
ArrayToHex関数は、uchar型の配列を16進数形式の文字列に変換するためのカスタム関数です。MQL5では、データをバイト配列で扱うことが多く、暗号化処理後の結果やバイナリデータを人間が読みやすい形式に変換するために使用されます。この関数は特に、暗号化されたデータを16進数表記で確認したい場合に役立ちます。
1. 引数の解説
- 第1引数:
uchar &arr[]
この引数は、変換対象のバイト配列です。uchar型は符号なし8ビット整数であり、バイト単位のデータを格納します。この配列の中身が、16進数形式に変換されます。 - 第2引数:
int count=-1
countは、変換するバイト数を指定する引数です。デフォルト値は-1で、特に指定がない場合には、配列のサイズ全体を変換対象とします。この引数に正の数値を渡すと、そのバイト数だけが変換されます。
2. 処理の流れ
- 初期化
関数内で、まず結果を格納するためのstring型変数resが空文字列で初期化されます。この変数に変換後の16進数表記が順次追加されていきます。 - 配列サイズの確認
countが負の値、または配列のサイズを超える場合、countを配列のサイズに設定します。これにより、変換対象のデータが適切に制限されます。 - 16進数変換のループ
forループを使って、配列内の各バイトデータを1つずつ処理します。StringFormat関数を用いて、各バイトを2桁の16進数にフォーマットし、それをresに追加していきます。%.2Xのフォーマット指定子は、バイト値を2桁の16進数で表記するために使用されます。 - 結果を戻り値として返す。
すべてのバイトを処理した後、resに格納された16進数表記の文字列を返します。これにより、バイトデータが視覚的に確認しやすい形式で取得できます。
3. 使用場面
この関数は、暗号化やバイナリデータの取り扱い時に役立ちます。例えば、暗号化後のデータをログに出力する際に、この関数を使用して16進数形式に変換することで、データの内容を可視化できます。また、暗号化の正当性を検証する場合にも、元のデータと暗号化されたデータを比較する際に利用されます。
サンプルコード解説2:OnStart関数その1
//+------------------------------------------------------------------+
//| スクリプトプログラムを開始する関数 |
//| OnStart関数は、スクリプト実行時に呼び出される自動的なエントリーポイントです |
//+------------------------------------------------------------------+
void OnStart()
{
string text="The quick brown fox jumps over the lazy dog"; // 暗号化する元のテキスト
string keystr="ABCDEFG"; // 暗号化に使用するキー
uchar src[], dst[], key[]; // データ配列(src: 元データ, dst: 暗号化されたデータ, key: 暗号化キー)
OnStart関数は、スクリプトが実行される際に最初に呼び出される関数であり、スクリプトのエントリーポイントとなります。この関数では、暗号化と復号(暗号化されたデータを元のデータに戻すこと)のための準備が行われます。以下は、その一部についての詳細な解説です。
1. 暗号化するテキストとキーの準備
- text変数
この変数には、暗号化対象の文字列が格納されています。この例では、”The quick brown fox jumps over the lazy dog” というテキストを暗号化します。このテキストは、暗号化の処理対象として配列に変換されます。 - keystr変数
暗号化に使用するキーを保持する文字列変数です。この例では、”ABCDEFG” という簡単な文字列がキーとして使用されています。暗号化アルゴリズムによっては、キーの長さや内容が暗号の強度に影響を与えるため、実際の用途では適切な長さと内容のキーを選ぶ必要があります。
2. 配列の初期化
- src配列、dst配列、key配列
src配列は、暗号化対象のデータを保持するためのバイト配列です。text変数に格納された文字列データが、後にこの配列に変換されます。
dst配列は、暗号化後のデータを格納するための配列です。この配列は、CryptEncode関数によって暗号化されたデータが格納されます。
key配列は、暗号化キーを保持するバイト配列です。keystr変数から、この配列にキーを変換して格納します。
これらの準備により、暗号化および復号のプロセスが開始される前段階が整えられます。
サンプルコード解説3:OnStart関数その2
StringToCharArray(keystr, key);
//--- テキストをsrc配列に変換する(文字列をバイト配列にコピー)
StringToCharArray(text, src);
//--- 初期データの情報を出力する
PrintFormat("Initial data: size=%d, string='%s'", ArraySize(src), CharArrayToString(src));
// 配列サイズと文字列としての内容を出力
//--- src配列をkey配列を使ってDES 56ビットキーで暗号化
int res = CryptEncode(CRYPT_DES, src, key, dst);
// CRYPT_DES方式で暗号化を実行し、結果をdst配列に格納
この部分では、文字列データをバイト配列に変換し、暗号化処理を実行しています。
1. 文字列をバイト配列に変換
- StringToCharArray関数によるキーの準備
StringToCharArray(keystr, key) によって、キー文字列 “ABCDEFG” がバイト配列である key に変換されます。これにより、暗号化処理に使用できる形式のキーが用意されます。 - テキストをバイト配列に変換
次に、StringToCharArray(text, src) を使って、暗号化対象のテキスト “The quick brown fox jumps over the lazy dog” が src 配列に変換されます。この配列は、暗号化の入力データとなります。
2. 初期データの出力
- PrintFormat関数でのデータ出力
PrintFormat関数を使用して、変換されたデータの配列サイズ(バイト数)と、その内容を確認するために文字列形式で出力します。ArraySize(src) は src 配列のサイズを取得し、CharArrayToString(src) はバイト配列を再び文字列に戻して表示します。このステップにより、暗号化前のデータをエキスパートログで確認できます。
3. 暗号化の実行
- CryptEncode関数による暗号化
CryptEncode(CRYPT_DES, src, key, dst) では、DES(データ暗号化標準)方式を使用して、src 配列のデータを key 配列のキーで暗号化し、その結果を dst 配列に格納します。DESは56ビットのキーを使用した古典的な暗号化アルゴリズムで、暗号化の結果がバイト配列dst に保存されます。
サンプルコード解説4:OnStart関数その3
//--- 暗号化処理が成功したか確認
if(res > 0)
{
//--- 暗号化されたデータを16進数形式で表示
PrintFormat("Encoded data: size=%d %s", res, ArrayToHex(dst));
// 暗号化後のデータサイズと16進数形式の内容を出力
//--- 暗号化されたdst配列をsrc配列にデコードする
res = CryptDecode(CRYPT_DES, dst, key, src);
// 同じキーとDES方式でデコードを実行
//--- デコードが成功したか確認
if(res > 0)
{
//--- デコードされたデータを表示
PrintFormat("Decoded data: size=%d, string='%s'", ArraySize(src), CharArrayToString(src));
// デコードされたデータのサイズと文字列を出力
}
else
Print("Error in CryptDecode. Error code=", GetLastError());
// デコードエラーが発生した場合のエラーメッセージを出力
}
このセクションでは、暗号化と復号(デコード)処理の結果を確認し、エラー処理を行う部分を解説します。
1. 暗号化処理の結果確認
- 暗号化が成功したかの確認
res > 0 の条件で、暗号化が正常に行われたかを確認します。このresは、CryptEncode関数の戻り値であり、暗号化が成功した場合には暗号化後のデータサイズ(バイト数)が返されます。成功していれば、そのサイズを基に次の処理に進みます。 - 暗号化されたデータの表示
PrintFormat関数を使用して、暗号化されたデータのサイズと、その内容を16進数形式で出力します。ArrayToHex関数を使用してバイト配列を16進数形式に変換し、暗号化された内容を視覚的に確認できるようにしています。
2. 暗号化データの復号(デコード)
- CryptDecode関数による復号
CryptDecode(CRYPT_DES, dst, key, src) では、DES方式を使用して、暗号化されたdst配列のデータをsrc配列に復号します。この際、暗号化に使用したのと同じキーでデコードを実行します。デコードによって、元のテキストデータがsrc配列に復元されます。
3. 復号処理の結果確認
- デコードが成功したかの確認
res > 0 でデコードが成功したかをチェックします。デコードが成功すると、デコード後のデータサイズが戻り値として返されます。 - デコードされたデータの表示
デコードが成功した場合、PrintFormat関数を使って復号されたデータを表示します。ArraySize(src) で復号後の配列サイズを取得し、CharArrayToString(src) でバイト配列を再び文字列に変換して出力します。これにより、元の文字列が正しく復元されたことが確認できます。
4. エラー処理
- エラーメッセージの表示
デコードに失敗した場合は、Print関数を使用してエラーメッセージを表示し、GetLastError関数でエラーコードを取得してエキスパートログに出力します。
サンプルコード解説5:OnStart関数その4
else
Print("Error in CryptEncode. Error code=", GetLastError());
// 暗号化エラーが発生した場合のエラーメッセージを出力
}
この最後の部分では、暗号化が失敗した場合のエラーメッセージ出力と、その処理について説明します。
1. 暗号化エラーの確認
- 暗号化失敗時の処理
CryptEncode関数の実行結果を確認した際、戻り値が0以下の場合は暗号化が失敗したことを意味します。その場合、if文のelseブロックが実行されます。ここでは、暗号化エラーが発生したことを示すメッセージをエキスパートログに出力します。
2. エラーメッセージの出力
- Print関数を使用してエラーメッセージを表示
Print関数を使用して、「Error in CryptEncode」というメッセージと、エラーコードをエキスパートログに出力します。エラーコードは、GetLastError関数を使用して取得されます。このエラーコードによって、何が原因で暗号化が失敗したかを確認できます。エラーコードの内容を調べることで、具体的な問題点を特定し、対応策を講じることができます。