Crypt::CBC
各種のブロック暗号アルゴリズムモジュールをCBCモードで利用して暗復号を実行する。
use Crypt::CBC;
パッケージをロードする
my $crypt = Crypt::CBC->new(-key => pack('H*',$key), -literal_key => 1, -keysize
=> $ks, -iv => pack('H*',$iv),
-cipher => $algo,-header => 'none');
鍵とIVを直接入力してインスタンスを生成する場合は、こんな感じ。
$algo には暗号アルゴリズムを指定する。'DED_EDE3', 'OpenSSL::AES' の様なCryptモジュールの名前。デフォルトは
Crypt::DES
-keysize の指定は必須ではないが、複数の鍵長が認められているアルゴリズムでは、指定しないと意図した鍵長が使われない場合がある。
例えば、Crypt::OpenSSL::AES では、Crypt::OpenSSL::AES::keysize() 関数が常に32を返すので、-keysize
を指定しないと 256bit鍵以外はエラーになってしまう。
この状態だと、-padding = standard
がデフォルトなのでPKCS#5に基づいたpaddingが実行される。このpaddingは、暗号文のデータサイズは平文のデータサイズより必ず大きくなる(平文データがブロックサイズの倍数に等しい場合でもpaddingデータが付加される)。
大きくなると困る場合は、'null' か 'space'
を使う。これらは、単純に0x00か0x20をpaddingする。復号時には0x00,0x20を除去してしまうので、平文の末尾のこれらのデータが意味を持つ場合はダメである。
'rijndael_compat'
だとバイナリセーフで、且つ、データサイズを増やさない事になっているが、平文データは8バイト(=64bit)の倍数でないとダメなので、ほとんど意味がない…
my $crypt = Crypt::CBC->new(-key => 'password', -iv => pack('H*', $iv),
-cipher => $algo, -header => 'none');
パスフェーズを元に鍵を生成してインスタンスを生成する場合は、こんな感じ。IV値は直接入力する必要がある。
同じパスフェーズを指定すれば、同じ鍵が生成されるので、暗号化/復号化ともCrypt::CBCで行なう場合は、バイナリの鍵値を直接入出力せずに暗復号できる。Crypt::CBC以外で復号する場合は、パスフェーズから鍵を生成するアルゴリズム(MD5ハッシュベースのアルゴリズム)を実装して鍵を復元する必要があるので、下記の方法がお勧め。
my $crypt = Crypt::CBC->new(-key => 'password', -cipher => $algo);
パスフェーズを元に毎回違う鍵,
IVを生成してインスタンスを生成する場合は、こんな感じ。乱数(salt)とパスフェーズを元に鍵とIVが生成され、saltの値がOpenSSL互換ヘッダに付加される。復号時にはパスフェーズとヘッダのsaltを元に鍵とIVが復元される。
OpenSSL互換のシステムとデータ交換を行う場合は、バイナリの鍵値を直接入出力せずに暗復号できる。
saltの値は、暗号化時のみ、-salt
パラメタで入力する事もでき、同じsaltを入力すれば毎回同じ鍵とIVが生成されるが、あまり意味がないかも…
$crypt->start('encrypt'); or $crypt->start('decrypt');
crypt() メソッドの暗復号方向を指定する。
my $output = $crypt->crypt($input);
暗復号を実行する。入出力はバイナリデータ表現。複数ブロックのデータを一度に入力することもできるし、複数回に分けて繰り返し入力する事もできる。
$output .= $crypt->finish();
ブロック長未満の端数データを出力して暗復号を終了する。入力データがブロック長の倍数である場合でも、padding処理などのためにモジュール内部に出力データが保留されている場合があるので、必ず実行すること。
my $output = $crypt->encrypt($input); または my $output =
$crypt->decrypt($input);
暗復号を実行する。cryptメソッドの替りに使える。このメソッドの場合は、startメソッドは要らない。
my $output = $crypt->encrypt_hex($input); または my $output = $crypt->decrypt_hex($input);
16進表現された入力データを暗復号化して16進表現された出力データを返す。このメソッドの場合は、startメソッドは要らない。
my $key = $crypt->key();
生成された鍵を取得する。引数を指定すると鍵の値を書き換えることもできるが、他のパラメタと不整合だと色々エラーが出て面倒。全てのパラメタはコンストラクタに指定して整合チェックをコンストラクタで終わらせておくのがお勧め。
manページでは、暗号化時には start() 実行後、復号化時には最初の crypt()
実行後に鍵生成される事になっているが、実際に試してみると暗復号ともに crypt() 実行後でないと鍵の値が返ってこない。
my $iv = $crypt->iv();
生成されたIV値を取得する。引数を指定するとIVの値を書き換えることもできる。
試してないが、これも crypt() 実行後でないとダメだろう。
他の暗号利用モード:
ECB, OFB, CFB を実行するモジュール Crypt::ECB, Crypt::OFB, Crypt::CFB
もあるが、インストール時に”現在メンテナンスしている人がいない”という警告が出たり、インタフェースがこなれていなかったりするので、Crypt::CBCを改造して自分で作る方が簡単である。
crypt() と finish()
を数行書き換えればOK。CTRも同様に作れる。ECBの場合、IV廻りのコードが余分になるが、使わなければいいだけ。