Perl を使って DES/MD5 の暗号化メモ(2002/11/26) 
 

DES/MD5 について

暗号化の技術は色々とありますが、Perl で簡単に使える暗号化は、DES と MD5 方式がありcrypt関数によって簡単に使用することができます。
ただしこの DES と MD5 は、使用する際に若干問題があり、システムによっては 片方しか使えなかったりしますので、予め下記のスクリプトを実行してみてどちらが使用可能かどうかを先に調べておく必要があります。(エラーが出たら、その方式は使えないということです

print "MD5 : " .crypt ('hogehoge','$1$hoge');
print "DES : " .crypt ('hogehoge','ja'); 

DES と MD5 では、同じパスワードを暗号化しても、暗号化された結果は異なるため、DES 方式で暗号化された結果を、異なるシステム(MD5 方式しか使えない)でパスワードを照合した結果、異なる結果となります。故にパスワードを照合できないって事です。

  参考 : DES と MD5

  参考 : crypt関数

  参考 : Perl5 用 DES crypt ライブラリ 

実際「暗号」という単語の対となる言葉として「復号」とありますが、「暗号」は「復号」ができて初めて使える言葉なのです。この crypt関数の場合は、crypt された暗号化の結果から元の文字列(暗号化する前の文字列)を取得する事ができないので、「暗号」とは言えません。
じゃなんて呼ぶの? というと「暗号」するだけの一方通行だけなので「ハッシュ関数」と通常は言います。暗号の強度を比べると、DES方式より MD5方式の方が高いので、通常は MD5方式を使うみたいですね。

また MD5方式の使用として、最近ではファイルの整合性チェックに使用されたり、公開しているファイルにウイルスなどを入れられてしまっていないように整合性チェックを行う場合に、ファイルサイズ/リンク/等の情報をMD5方式で暗号化し、その文字列をファイルと共に付加し正しいもの(オリジナル)である事の証明のために使用されたりしています。

暗号化するためには、オリジナルの文字列とsalt係数(サルト)とを掛け合わせて暗号化文字列(正しくは、ハッシュ文字列)を作成しますが、作成された暗号化文字列を見ると、DES の場合は salt は2文字で、「XXYYYYYYY」という形式になります。MD5 の salt は8文字 (以内) で、「$1$XXXXXX$YYYYYYYY$」となります (色の部分が salt です)。 

暗号化する意味をここでは再度説明しますが、素のパスワードをファイルやデータベースにそのまま保存することは、ハッキングや第三者の目に触れたとき簡単に悪用されてしまうという危険性があります。ですので、DES や MD5方式で暗号化(ハッシュ文字列)された文字列を保存することによりパスワードが簡単に分からない様にするのが一般的です。※総辺り方式で解析できないこともないのですけど、膨大な時間がかかります

説明が長くなりましたが、プログラムの説明です(MD5)

1.サルト係数を作成します。

srand();
@salts = ( "A".."Z", "a".."z", "0".."9", ".", "/" );
$salt = $salts[int(rand(64))] . $salts[int(rand(64))];

2.オリジナルの文字列からサルト係数を足し暗号化文字列を作成します。

$pass_org = "murachi";
$pass_md5 = crypt($pass_org, '$1$' . $salt);
print "pass_org=$pass_org\n";
print "pass_md5=$pass_md5\n";

$pass_md5 変数に入っている文字列が、暗号化文字列です。この文字列をファイルやデータベースに保存しておきます。

3.暗号化(ハッシュ文字列)された文字列と、オリジナルの文字列の比較をします。

$pass_org = "murachi";
if ($pass_md5 eq crypt($pass_org, $pass_md5 )) {
   print "MD5 Match!!\n";
}

"MD5 Match!!"と表示されれば、比較が正しく行われた事をさします。

DES/MD5 方式のプログラムサンプル

1.DES方式です。

$pass_org = "murachi";

# 暗号化する
srand();
@salts = ( "A".."Z", "a".."z", "0".."9", ".", "/" );
$salt = $salts[int(rand(64))] . $salts[int(rand(64))];
$pass_des = crypt($pass_org, $salt);
print "pass_org=$pass_org\n";
print "pass_des=$pass_des\n";

# 暗号化された文字列のチェック
if ($pass_des eq crypt($pass_org, $pass_des)) {
   print "DES Match!!\n";
}

2.MD5方式です。

$pass_org = "murachi";

# 暗号化する
srand();
@salts = ( "A".."Z", "a".."z", "0".."9", ".", "/" );
$salt = $salts[int(rand(64))] . $salts[int(rand(64))];
$pass_md5 = crypt($pass_org, '$1$' . $salt);
print "pass_org=$pass_org\n";
print "pass_md5=$pass_md5\n";

# 暗号化された文字列のチェック
#$pass_md5 =~ s/\$1\$(.*)\$/\1/;
if ($pass_md5 eq crypt($pass_org, $pass_md5 )) {
   print "MD5 Match!!\n";
}