Perlでブロック暗号を利用する (BlowfishとCBCモード)
任意長のデータ列に対してブロック暗号を適用するためには,ECB (Electric Code Block; c[i] = E(m[i])
) やCBC (Cipher Block Chaining; c[i] = E(m[i] \xor c[i-1])
)といったモードを使う必要がある.
この記事では,Perl から 8bitブロック暗号 Blowfish をモード CBC で利用する方法を説明する.
CBCモード暗号器の作成
Perl で CBC モードでの暗号化を実現するには,CPAN モジュールの Crypt::CBC を使うと簡単だ. まず,以下のように暗号器を作成する.
use Crypt::CBC; my $cipher = Crypt::CBC->new( -key => 'my secret key', -cipher => 'Crypt::Blowfish', );
コンストラクタのオプションの意味は以下のとおり.
-key
はパスフレーズを指定する.暗号アルゴリズムの鍵として使用される.-cipher
は暗号アルゴリズムを指定し,現在Crypt::DES
,Crypt::DES_EDE3
,Crypt::IDEA
,Crypt::Blowfish
,Crypt::CAST5
,Crypt::Rijndael
が利用可能
一般的に,CBCを利用するためには 初期化ベクタ (IV; 式上のパラメータでいうと c[-1]
) を
適当に決める必要がある.
デフォルトでは,Crypt::CBC
はランダムにsalt値を生成し,それをもとにIV作成(とパスフレーズのハッシュ化)を行っている.
saltは暗号データの先頭に付与し,復号処理と共有する.
暗号器の利用
作成した暗号器を使い,データを暗号化する方法は以下の通り. 非常に簡単だ.
# 方法その1 $cipher->start( 'encrypting' ); open( FH, "./BIG_FILE" ); $crypted =. $cipher->crypt( $buf ) while ( read(FH, $buf, 1024) ); $crypted =. $cipher->finish; # 方法その2 (より簡単な方法) $crypted = $cipher->encrypt( $plaintext );
復号する場合も似たようにやれば良い.
# 方法その1 $cipher->start( 'decrypting' ); open( FH, "./BIG_CRYPT_FILE" ); $plain =. $cipher->crypt( $buf ) while ( read(FH, $buf, 1024) ); $plain =. $cipher->finish; # 方法その2 (より簡単な方法) $plain = $cipher->decrypt( $crypted_data );
暗号化データをバイナリではなくてテキストとして使用したい場合(例えば e-mail の本文に張り付けるなど),暗号データを16進表現するメソッドが用意されている.
# 暗号化.unpack('H*', $cipher->encrypt( $plaintext )) と等価 $crypted_hex = $cipher->encrypt_hex( $plaintext ); # '53616c7465645f5f7683738451b858c8497fcd081044f63b' のようになる print $crypted_hex . "\n"; # 復号 $plain = $cipher->decrypt_hex( $crypted_hex );
速度に関する備考
Crypt::CBC
の perldocには,速度が等価なSSLeayプログラムに比して10倍ほど遅いとの記述がある.
速度を求めるなら直接Cライブラリを叩いたほうがいいかもしれない.