CryptEncode関数の働き・役割
CryptEncode関数は、指定された暗号化手法を使用して、データ配列を暗号化するために使用されます。具体的には、配列データを指定された暗号化キーと暗号化方式に基づいて変換し、その結果を別の配列に格納します。この関数は、ENUM_CRYPT_METHODで指定される暗号化方式に対応しており、一般的な暗号化手法としてDES(データ暗号化標準)やAES(高度暗号化標準)などが使用可能です。
暗号化されたデータのバイト数が戻り値として返され、暗号化処理が正常に行われなかった場合は0が返されます。エラーの詳細はGetLastError関数で確認できます。
CryptEncode関数の引数について
CryptEncode
指定されたメソッドを使用して配列からデータを変換します。
int CryptEncode(
ENUM_CRYPT_METHOD method, // 方法
const uchar& data[], // ソース配列
const uchar& key[], // キー
uchar& result[] // ターゲットの配列
);
CryptEncode関数は、4つの引数を取ります。
第1引数: method
第1引数は、暗号化方式を指定するもので、ENUM_CRYPT_METHODのいずれかの値を使用します。この列挙型には、DES(データ暗号化標準)やAES(高度暗号化標準)などの暗号化アルゴリズムが含まれます。
※ENUM_CRYPT_METHODについての詳細は↓の記事をご覧ください。
第2引数: data[]
第2引数は、暗号化対象の配列を指定します。この配列は、uchar型(符号なし8ビット整数)で定義されるバイト配列であり、暗号化したいデータが格納されています。
第3引数: key[]
第3引数は、暗号化に使用するキー配列を指定します。このキーもuchar型の配列で、暗号化方式に応じた適切な長さのキーが必要です。例えば、DES方式では56ビットのキーが必要になります。
第4引数: result[]
第4引数は、暗号化されたデータを格納するための配列を指定します。この配列は、関数実行後に暗号化されたデータを受け取るために使用されます。配列はuchar型のバイト配列で、関数が正常に実行されると暗号化されたデータがここに格納されます。
CryptEncode関数の戻り値について
CryptEncode関数の戻り値は、暗号化が成功した場合、暗号化されたデータのバイト数が返されます。これにより、暗号化後のデータがどのくらいのサイズで格納されたかを確認することができます。
一方、暗号化が失敗した場合は0が返されます。この場合、何らかのエラーが発生しているため、エラーコードを確認する必要があります。エラーの詳細はGetLastError関数を使用して取得可能です。
CryptEncode関数を使ったサンプルコード
//+------------------------------------------------------------------+
//| 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関数を使用して取得されます。このエラーコードによって、何が原因で暗号化が失敗したかを確認できます。エラーコードの内容を調べることで、具体的な問題点を特定し、対応策を講じることができます。