「Qtの応用 - AES」の版間の差分

ナビゲーションに移動 検索に移動
79行目: 79行目:
<br>
<br>
カウンタモードであれば、安全性が若干損なう可能性があるが、暗号化も復号もランダムに行えて便利である。<br>
カウンタモードであれば、安全性が若干損なう可能性があるが、暗号化も復号もランダムに行えて便利である。<br>
<br><br>
== 暗号化ライブラリ ==
==== Crypto++ Libraryのダウンロード ====
[https://cryptopp.com Crypto++ Libraryの公式Webサイト]にアクセスして、暗号化ライブラリのソースコードをダウンロードする。<br>
ダウンロードしたソースコードをビルドする。<br>
make -j 8 static dynamic CXX=/<GCCのインストールディレクトリ>/g++
make test
make install DESTDIR=<暗号化ライブラリのインストールディレクトリ>
<br>
暗号化ライブラリの使用手順は、以下のWebサイトを参照すること。<br>
https://www.cryptopp.com/wiki/Advanced_Encryption_Standard<br>
<br>
==== Crypto++ Libraryの概要 ====
AES(またはその他のブロック暗号)を使用する時は、通常、ブロック暗号のインスタンスを持つモードを使用する。<br>
例えば、CFBモードの場合は、以下のように記述する。<br>
<syntaxhighlight lang="c++">
CFB_Mode<AES>::Encryption Encrypt;  // CFB_Modeは、ブロック暗号をテンプレートパラメータとして受け取る
</syntaxhighlight>
<br>
==== ブロック暗号の参照 ====
外部のブロック暗号オブジェクトのインスタンスではなく、そのオブジェクトへの参照を保持するモードオブジェクトを作成することもできる。<br>
以下の例では、外部のAESオブジェクトでCFBモードを使用している。<br>
<syntaxhighlight lang="c++">
AES::Encryption aesEncryption(key, AES::DEFAULT_KEYLENGTH);
CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv);
</syntaxhighlight>
<br>
ExternalCipherモードは、WindowsでFIPSをサポートするために追加されたものであり、必要がない限り避けるべきである。<br>
<br>
==== ECBおよびCBCモードの備考 ====
ECBおよびCBCモードでは、データをブロックサイズの倍数で処理する必要がある。<br>
または、<code>StreamTransformationFilter</code>をモードオブジェクトにラッピングして、フィルタオブジェクトとして使用することもできる。<br>
<code>StreamTransformationFilter</code>は、データをブロックにバッファリングして、必要に応じてパディングを行う。<br>
<br>
もし、フルブロックサイズで処理する(パディングを行わない)場合は、第4引数に<code>StreamTransformationFilter</code>の<code>NO_PADDING</code>を指定する。<br>
<syntaxhighlight lang="c++">
StringSource(data, true, new StreamTransformationFilter(encryptor, new StringSink(result), NO_PADDING))
</syntaxhighlight>
<br>
==== サンプルコード ====
以下の例では、AESが使用する鍵長の最小値、最大値、標準値をダンプしている。(2番目と3番目はパイプラインのフィルターを使用している)<br>
パイプラインは高レベルの抽象化であり、入力のバッファリング、出力のバッファリング、パディングを処理する。<br>
<syntaxhighlight lang="c++">
std::cout << "鍵長 : " << AES::DEFAULT_KEYLENGTH << std::endl;
std::cout << "鍵長(最小) : " << AES::MIN_KEYLENGTH << std::endl;
std::cout << "鍵長(最大) : " << AES::MAX_KEYLENGTH << std::endl;
std::cout << "ブロックサイズ : " << AES::BLOCKSIZE << std::endl;
// 出力
// 標準値の鍵長は128ビット(16バイト)
鍵長 : 16
鍵長(最小) : 16
鍵長(最大) : 32
ブロックサイズ : 16
</syntaxhighlight>
<br>
以下の例では、CFBモードを使用して、暗号化および復号を行っている。<br>
ECBやCBCではないため、データ長をAESのブロックサイズの倍数にする必要は無い。<br>
<syntaxhighlight lang="c++">
AutoSeededRandomPool rnd;
// Generate a random key
SecByteBlock key(0x00, AES::DEFAULT_KEYLENGTH);
rnd.GenerateBlock(key, key.size());
// Generate a random IV
SecByteBlock iv(AES::BLOCKSIZE);
rnd.GenerateBlock(iv, iv.size());
byte plainText[] = "Hello! How are you.";
size_tmessageLen = std::strlen((char*)plainText) + 1;
// Encrypt
CFB_Mode<AES>::Encryption cfbEncryption(key, key.size(), iv);
cfbEncryption.ProcessData(plainText, plainText, messageLen);
// Decrypt
CFB_Mode<AES>::Decryption cfbDecryption(key, key.size(), iv);
cfbDecryption.ProcessData(plainText, plainText, messageLen);
</syntaxhighlight>
<br>
ここでは、外部で生成された鍵と初期化ベクトル(IV)を使用して、暗号化器と復号器を取得する例を記述する。<br>
その後の処理は、上記の例と同様に記述する。<br>
<syntaxhighlight lang="c++">
SecByteBlock aes_key(16);
SecByteBlock iv(16);
// stub for how you really get it, e.g. reading it from a file, off of a
// network socket encrypted with an asymmetric cipher, or whatever
read_key(aes_key, aes_key.size());
// stub for how you really get it, e.g. filling it with random bytes or
//  reading it from the other side of the socket since both sides have
//  to use the same IV as well as the same key
read_initialization_vector(iv);
// the final argument is specific to CFB mode, and specifies the refeeding size in bytes.
// This invocation corresponds to Java's Cipher.getInstance("AES/CFB8/NoPadding")
auto enc = new CFB_Mode<AES>::Encryption(aes_key, sizeof(aes_key), iv, 1);
// the final argument is specific to CFB mode, and specifies the refeeding size in bytes.
// This invocation corresponds to Java's Cipher.getInstance("AES/CFB8/NoPadding")
auto dec = new CFB_Mode<AES>::Decryption(aes_key, sizeof(aes_key), iv, 1);
</syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:Qt]]
[[カテゴリ:Qt]]

案内メニュー