
はじめに
ウェブ制作において、会員ページの制作時には大抵暗号化の必要性が出てきます。
先日、ある無料ホームページサイトの会員管理情報17万件の流失事件がありました。 その際に、会員の平文パスワードも一緒に流失したそうです。どうやら、会員データベースに保存するパスワードは暗号化していなかったようです。やはり、大量の個人情報を保管する以上は、パスワードの暗号化は必須ではないでしょうか。
Perlで暗号を試みる際には、関数を利用する方法とモジュールを利用する方法に分けられると思います。
しかしながら、その使い方について、統合的に且つ初心者へも分かるような解説サイトをなかなか目にしないため、ここにPerlを使った暗号入門ページを作成することにしました。
暗号化の基本
シーザー暗号
シーザー暗号とは、古代ローマのジュリアス・シーザーが使ったとされる暗号方式です。
平文の各文字をアルファベット順に3文字だけシフトして暗号文を作ったとされています。
ABC -> DEF
実際には、シフトする文字数は3文字に限る必要はないので、状況に応じて「鍵」であるシフト数を変えればいいことになります。 また、この暗号を読む側も、「鍵」であるシフト数を知っていれば、容易に解読することができます。
現代でも、この暗号化とその復元というアルゴリズムは生きているといっていいでしょう。
現在では、このような機械的な暗号・復号の処理は、プログラムが得意とするところです。 これをPerlプログラムで作成してみると、次のように記述することができます(暗号・復号の対象文字は英小文字限定の場合です)。
01 use strict;
02
03 # 対象文字
04 my $passwd = ‘this is a pen.’;
05
06 # シフト数 (1 ~ 25 まで)
07 my $shift = 3;
08
09 # 暗号
10 my $crypt = &encrypt($passwd, $shift);
11 print “$crypt\n”;
12
13 # 復号
14 print &decrypt($crypt, $shift), “\n”;
15
16 #———————————————————–
17 # シーザー暗号
18 #———————————————————–
19 sub encrypt {
20 my ($wd, $shift) = @_;
21
22 # 対象文字
23 my @wd = (‘a’ .. ‘z’);
24
25 # 変換テーブル作成
26 my %wd;
27 for (0 .. $#wd) {
28 # 添字を定義
29 my $key = $_ <= $#wd – $shift ? $_ + $shift : $_ – $#wd + $shift – 1;
30
31 # ハッシュ生成
32 $wd{$wd[$_]} = $wd[$key];
33 }
34
35 # 変換テーブルにより暗号化
36 my $ret;
37 for ( split(//,$wd) ) {
38 # 定義済は変換
39 if (defined($wd{$_})) {
40 $ret .= $wd{$_};
41
42 # 未定義はそのまま
43 } else {
44 $ret .= $_;
45 }
46 }
47 return $ret;
48 }
49
50 #———————————————————–
51 # シーザー復号
52 #———————————————————–
53 sub decrypt {
54 my ($crypt, $shift) = @_;
55
56 # 対象文字
57 my @wd = (‘a’ .. ‘z’);
58
59 # 変換テーブル作成
60 my %wd;
61 for (0 .. $#wd) {
62 # 添字を定義
63 my $key = $_ <= $#wd + $shift ? $_ – $shift : $_ + $#wd – $shift + 1;
64
65 # ハッシュ生成
66 $wd{$wd[$_]} = $wd[$key];
67 }
68
69 # 復号
70 my $ret;
71 for ( split(//,$crypt) ) {
72 # 定義済は変換
73 if (defined($wd{$_})) {
74 $ret .= $wd{$_};
75
76 # 未定義はそのまま
77 } else {
78 $ret .= $_;
79 }
80 }
81 return $ret;
82 }
1 > wklv lv d shq.
2 > this is a pen.
上記のとおり、文字列を暗号し、さらに無事に元の文字列に戻すことができました。
古代の暗号方式はここまでにして、次からは近年の暗号方式についてです。
可逆式と不可逆式
近年の暗号方式を見ていく場合、文字列を暗号化するスタイルとして、「可逆式」か「不可逆式」かの2つがあります。
「可逆式」とは、一度暗号化したものを、そっくりそのまま元に戻せるものをいいます。 それに対して、「不可逆式」とは、一度暗号化すると、元の文字列に戻せない方式をいいます。
「不可逆式」の場合、元に戻せないような暗号化処理をするため、一般的には「可逆式」に比べて暗号化の強度が堅牢であるといえます。
ここで、「不可逆式」の場合に疑問に思う人がいるかもしれません。元に戻せない暗号文字を、どうやって元の文字列(平文)と照らし合わせるのかと。
それは、照らし合わせたい文字列の方(平文)を同様に暗号化して、同じ暗号文字になっているかどうかを比較すればいいことになります。 これをここでは「照合」と呼ぶことにしましょう。
ちなみに、「可逆式」の場合は、いったん元の文字列に戻す訳ですから、これを「復号」といいます。
スタイル | 特徴 | 復号・照合 |
可逆式 | 元の文字列に復元できる | 復号 |
不可逆式 | 元の文字列に復元できない 可逆式に比べて強固 | 照合 |
DESとMD5について
具体的な暗号化方式は、近年では次の2種が有名で、1つは「DES方式」、もう1つは「MD5方式」です。
いずれも、不可逆式の暗号化方式です。
「DES方式」とは、「Data Encryption Standard(データ暗号化標準)」の略で、1977年に開発された暗号化方式です。 56ビットの鍵を使った共通鍵暗号を基盤としており、アルゴリズムを広く公開した初めての暗号方式で、かつて広く普及していました。
しかしながら、最近では暗号強度が弱いとされ、あまり使われなくなってきました。
「MD5方式」の方は、「Message Digest Algorithm 5」の略で、1991年に開発された暗号化方式です。 128ビットのハッシュ値を出力するハッシュ関数で、DES方式に比較して暗号強度が強く、DES方式に取って代わりました。 しかし、ここ最近では弱点も次第に指摘されてくるようになってきました。
Perl関数で暗号化 – DES編
Perlの場合には、暗号のための関数として、crypt関数が用意されています。 この場合、暗号化方式は、サーバーのマシンに依存され、DES方式か又はMD5方式になります。
例えば、Linuxでは当初はDES方式のみをサポートしていましたが、最近ではMD5方式もサポートしているようです。 それに対してFreeBSDの場合は当初からMD5をサポートしていました。