Perl関数で暗号化 - MD5編
前章では、DES環境下でのcrypt関数について解説しましたが、本章ではMD5環境下でのcrypt関数について見ていきます。
3-1. デモ
今回のcrypt関数(MD5方式)のデモです。saltの8文字をアトランダムに付加し、パスワードを暗号化します。
3-2. MD5方式の場合
MD5方式下でcrypt関数を使用する場合には、$1$ で始まる8文字($1$ を含めて11文字)以内のsalt(種)を用意します。
| 関数 | 備考 |
|---|---|
| crypt(passwd, salt) |
passwd : 暗号化する文字列。8文字以内 salt : 英数字、ドット、スラッシュのいずれかの文字列で、0〜8文字を$1$〜$で囲む。 |
たとえば、saltを「12345678」とし、暗号化する文字列を「abcd」とします。
ちなみに、saltの末尾の「$」に限っては、これを省略しても構いません。
ちなみに、saltの末尾の「$」に限っては、これを省略しても構いません。
use strict; # パスワード my $passwd = 'abcd'; # salt my $salt = '$1$12345678$'; # 暗号化 my $crypt = crypt($passwd, $salt); print "$crypt\n";
> $1$12345678$N/3zBznjFuq/Ila9YecQl.
上記の出力内容で、先頭の「$1$12345678$」までがsaltで、それ以降の「N/3zBznjFuq/Ila9YecQl.」が暗号化文字となります。
DES方式と比べて、文字列も長く、強度が増していることが分かります。
次に、saltの8文字を自動化するコード例は次のとおりです。
use strict;
# パスワード
my $passwd = 'abcd';
# saltの8文字をアトランダムに生成
my @str = (0 .. 9, 'a' .. 'z', 'A' .. 'Z', '.', '/');
my $salt;
for (1 .. 8) {
$salt .= $str[int(rand(@str))];
}
# 暗号化
my $crypt = crypt($passwd, '$1$' . $salt . '$');
print "$crypt\n";
> $1$IHnmFf/z$9numQmChmSOOO1mz8odh/1
上記のコード例では、任意の8文字「」がsaltになっていますが、起動するたびに異なったsaltが取得され、それに連動して出力結果(暗号文字)も異なります。
上記の暗号化コードを、さらに使いやすいようにサブルーチン化してみます。
use strict;
# パスワード
my $passwd = 'abcd';
# 暗号化
print &encrypt($passwd);
#-----------------------------------------------------------
# MD5暗号化
#-----------------------------------------------------------
sub encrypt {
my $passwd = shift;
# salt生成
my @str = (0 .. 9, 'a' .. 'z', 'A' .. 'Z', '.', '/');
my $salt;
for (1 .. 8) {
$salt .= $str[int(rand(@str))];
}
# 暗号化
return crypt($passwd, '$1$' . $salt);
}
3-3. 暗号文字の照合
照合の仕方についてはDES方式と同じで、saltの取得方法が異なるだけです。
前章のときは substr関数で抜き出しましたが、今回はsaltの並び方がやや複雑なので、正規表現で抜き出してみましょう。
前章のときは substr関数で抜き出しましたが、今回はsaltの並び方がやや複雑なので、正規表現で抜き出してみましょう。
use strict;
# パスワード(元の文字列)
my $passwd = 'abcd';
# 暗号化された文字列
my $crypt = '$1$IHnmFf/z$9numQmChmSOOO1mz8odh/1';
# 暗号化された文字列からsaltを正規表現で取得
my $salt = $crypt =~ /^(\$1\$.*\$)/ && $1;
# 判定
if ($crypt eq crypt($passwd, $salt)) {
print "OK\n";
} else {
print "NG\n";
}
> OK
無事に照合ができました。
最後に、もっと使いやすくするために、サブルーチン化します。
use strict;
# パスワード
my $passwd = 'abcd';
# 暗号文字
my $crypt = '$1$IHnmFf/z$9numQmChmSOOO1mz8odh/1';
# 照合
if (&decrypt($crypt, $passwd)) {
print "OK\n";
} else {
print "NG\n";
}
#-----------------------------------------------------------
# MD5照合
#-----------------------------------------------------------
sub decrypt {
my ($crypt, $plain) = @_;
# salt抽出
my $salt = $crypt =~ /^(\$1\$.*\$)/ && $1;
# 判定
return $crypt eq crypt($plain, $salt) ? 1 : 0;
}
Cryptography in Perl

powered by
Profile

