Perlモジュールで暗号化 - Crypt::RC4編
可逆式の暗号方式で、ストリーム暗号の代表格である「RC4」を紹介しておきます。
RC4は1987年に開発されたストリーム暗号であり、WEP(無線LANの標準仕様)やWinny(ファイル共有ソフト)、SSLやSSH等、広く利用されている暗号化方式です。
特徴として、DESと比較して高速であり、鍵の長さをある程度任意に設定できる点も挙げられています。
特徴として、DESと比較して高速であり、鍵の長さをある程度任意に設定できる点も挙げられています。
10-1. デモ
Crypt::RC4のデモです。文字列をRC4形式に変換します。
10-2. Crypt::RC4モジュール
Crypt::RC4モジュールは、PerlでRC4暗号アルゴリズムを利用するためのものです。
モジュールファイルが非常にシンプルにできており、扱いやすいという特性があります。 しかしその反面、hex/Base64出力のための関数などが用意されておらず、RC4モジュールを使った暗号/復号を補完する処理を作りこむ必要があります。
モジュールファイルが非常にシンプルにできており、扱いやすいという特性があります。 しかしその反面、hex/Base64出力のための関数などが用意されておらず、RC4モジュールを使った暗号/復号を補完する処理を作りこむ必要があります。
基本構文は次のとおりです。
関数形式 |
use Crypt::RC4; $encrypted = RC4( $passphrase, $plaintext ); $decrypt = RC4( $passphrase, $encrypted ); |
---|---|
OO形式 |
use Crypt::RC4; $ref = Crypt::RC4->new( $passphrase ); $encrypted = $ref->RC4( $plaintext ); |
ちなみに、Crypt::RC4は標準モジュールではないため、個別にインストールする必要があります。
ご参考 :
【コラム】Perlモジュールの組み込み
10-3. 暗号と復号
暗号化のコードを考える場合、Crypt::RC4モジュールは、バイナリをテキストへ変換するためのhex/Base64変換の関数が用意されていないため、自前で作成する必要があります。
hex形式を扱う場合には、Perlでは、pack/unpack関数を使用します。
構文は次のとおりです。
それから、もう一点注意することがあります。RC4 + hex変換した場合に16進文字列の中に「改行」が混じることがあります。
改行を含む文字列をそのまま保管するのは扱いにくいため、この場合は改行を「n」に置き換えておくことにします(16進数の場合、nは使用しない)。
方式 | 構文 | 内容 |
---|---|---|
16進文字列→バイナリ文字列 | pack('H2', text) | textという16進文字列をバイナリ文字列へ変換して返す |
バイナリ文字列→16進文字列 | unpack('H2', bin) | binというバイナリ文字列を16進文字列へ変換して返す |
改行を含む文字列をそのまま保管するのは扱いにくいため、この場合は改行を「n」に置き換えておくことにします(16進数の場合、nは使用しない)。
use strict; # モジュールを宣言 use Crypt::RC4; # パスワード my $passwd = '春はあけぼの'; # 秘密鍵 my $key = '清少納言'; # RC4暗号変換 my $crypt = RC4($key, $passwd); # hex処理 $crypt =~ s/(.)/unpack('H2', $1)/eg; $crypt =~ s/\n/n/g; # 出力 print "$crypt\n";
> 8883f2eb71762aa08868fa6a
次に、復号方法(hex形式)は次のとおりです。
use strict; # モジュールを宣言 use Crypt::RC4; # 暗号文字 my $crypt = '8883f2eb71762aa08868fa6a'; # 秘密鍵 my $key = '清少納言'; # 16進をバイナリへ戻す $crypt =~ s/n/\n/g; $crypt =~ s/([0-9A-Fa-f]{2})/pack('H2', $1)/eg; # RC4復号 my $plain = RC4($key, $crypt); print "$plain\n";
> 春はあけぼの
暗号/復号のためのコード(hex形式)を1つにまとめてみましょう。
use strict; # モジュールを宣言 use Crypt::RC4; # パスワード my $passwd = '春はあけぼの'; # 秘密鍵 my $key = '清少納言'; # RC4暗号 my $crypt = &encrypt($key, $passwd); print "$crypt\n"; # RC4復号 my $plain = &decrypt($key, $crypt); print "$plain\n"; #----------------------------------------------------------- # RC4暗号 #----------------------------------------------------------- sub encrypt { my ($key, $plain) = @_; # RC4暗号変換 my $crypt = RC4($key, $plain); # バイナリを16進へ $crypt =~ s/(.)/unpack('H2', $1)/eg; $crypt =~ s/\n/n/g; # 出力 return $crypt; } #----------------------------------------------------------- # RC4復号 #----------------------------------------------------------- sub decrypt { my ($key, $crypt) = @_; # バイナリへ戻す $crypt =~ s/n/\n/g; $crypt =~ s/([0-9A-Fa-f]{2})/pack('H2', $1)/eg; # RC4暗号変換 return RC4($key, $crypt); }
> 8883f2eb71762aa08868fa6a > 春はあけぼの
10-4. Base64形式の場合
Base64形式でのコードも考えてみます。
Base64に変換するには、標準モジュールであるMIME::Base64モジュールを使用します。
今回MIME::Base64モジュールの使い方で注意するところは、 encode_base64()関数のところで、デフォルトでは「改行」を含んだ複数の文字列に分割した値を返すため、オプションで改行を含まない1行の文字列を返すように指定します。
その場合、2番目の引数として以下のように空白の文字列を渡します。
Base64に変換するには、標準モジュールであるMIME::Base64モジュールを使用します。
概要 |
use MIME::Base64; $encoded = encode_base64('Aladdin:open sesame'); $decoded = decode_base64($encoded); |
---|
その場合、2番目の引数として以下のように空白の文字列を渡します。
encode_base64($str, '')
このことを意識しながら、Base64出力での暗号化のコード例を記述してみます。
hex形式よりコンパクトに書けました。
hex形式よりコンパクトに書けました。
use strict; # モジュールを宣言 use Crypt::RC4; use MIME::Base64; # パスワード my $passwd = '明日デート決行'; # 秘密鍵 my $key = '極秘'; # RC4暗号 my $crypt = encode_base64(RC4($key, $passwd), ''); print "$crypt\n"; # RC4復号 print RC4($key, decode_base64($crypt)), "\n";
> hLOjHFIba2e2xwiJhHE= > 明日デート決行