Perlモジュールで暗号化 - Digest::SHA1編
最近では、MD5も次第に研究されてきて、いろいろと弱点も指摘されているようです。
そこで、当然ながら他の暗号方式も考案されてきました。
その1つが、SHA-1(エスエイチエー、Secure Hash Algorithm)です。 MD5方式に比べて、攻撃に強いとされています。
その1つが、SHA-1(エスエイチエー、Secure Hash Algorithm)です。 MD5方式に比べて、攻撃に強いとされています。
そのSHA-1アルゴリズムへのPerlインターフェースとして、Digest::SHA1モジュールがあります。
7-1. デモ
Digest::SHA1のデモです。文字列をSHA-1形式で変換します。
7-2. Digest::SHA1モジュール
Digest::SHA-1モジュールも、Digest::MD5と同様に標準モジュールとして採用されています。
データ長は、バイナリ形式では20ビットで、hex形式で40文字、Base64形式で27文字となります。
データ長は、バイナリ形式では20ビットで、hex形式で40文字、Base64形式で27文字となります。
基本構文は次のとおりです。Digest::MD5とほぼ同じであることが分かります。
関数形式 |
use Digest::SHA1 qw(sha1 sha1_hex sha1_base64); $digest = sha1($data); $digest = sha1_hex($data); $digest = sha1_base64($data); |
---|---|
OO形式 |
use Digest::SHA1; $ctx = Digest::SHA1->new; $ctx->add($data); $ctx->addfile(*FILE); $digest = $ctx->digest; $digest = $ctx->hexdigest; $digest = $ctx->b64digest; |
コード例は次のとおりです。
use strict; # モジュールを宣言 use Digest::SHA1 qw(sha1_hex); # 文字列 my $str = 'abcd'; # MD5変換(hex形式) my $digest = sha1_hex($str); print "$digest\n";
> 81fe8bfe87576c3ecb22426f8e57847382917acf
hex形式で、上記のとおり40文字で出力されました。
ここで、MD5形式との特徴を確認しておきましょう。一般的に、データ長が長いほど、強度が強いということが言えます。
データ長 | hex表記 | Base64表記 | |
---|---|---|---|
SHA-1 | 20ビット | 40文字 | 27文字 |
MD5 | 16ビット | 32文字 | 22文字 |
7-3. 暗号として使うには
Digest::SHA-1を暗号ツールとして利用する場合は、第5章の使い方と同じです。
saltをランダムな8文字としたコード例です。
saltをランダムな8文字としたコード例です。
use strict; # モジュールを宣言 use Digest::SHA1 qw(sha1_hex); # 文字列 my $passwd = '1234'; # saltの8文字を16進法式でアトランダムに生成 my @str = ('a' .. 'f', 0 .. 9); my $salt; for (1 .. 8) { $salt .= $str[int(rand(@str))]; } # SHA1変換(hex形式) my $digest = $salt . sha1_hex($salt . $passwd); print "$digest\n";
> 81fe8bfe87576c3ecb22426f8e57847382917acf
次に、照合処理です。
暗号文字の先頭の8文字を抜き出し、SHA-1(hex) 変換して、照合することになります。
暗号文字の先頭の8文字を抜き出し、SHA-1(hex) 変換して、照合することになります。
use strict; # モジュールを宣言 use Digest::SHA1 qw(sha1_hex); # パスワード my $passwd = '1234'; # 暗号文字 my $crypt = '81fe8bfe87576c3ecb22426f8e57847382917acf'; # saltは先頭の8文字を抜き出す my $salt = substr($crypt, 0, 8); # 判定 if ($crypt eq ($salt . sha1_hex($salt . $passwd))) { print "OK\n"; } else { print "NG\n"; }
> OK
上記の暗号/照合コードをサブルーチン化すると、次のようになります(hex形式の場合)。
use strict; # モジュールを宣言 use Digest::SHA1 qw(sha1_hex); # 文字列 my $passwd = '1234'; # 暗号 my $crypt = &encrypt($passwd); print "$crypt\n"; # 照合 if (&decrypt($crypt, $passwd)) { print "OK\n"; } else { print "NG\n"; } #----------------------------------------------------------- # Digest::SHA-1 (hex) 暗号化 #----------------------------------------------------------- sub encrypt { my $plain = shift; # saltの8文字を16進でアトランダムに生成 my @str = ('a' .. 'f', 0 .. 9); my $salt; for (1 .. 8) { $salt .= $str[int(rand(@str))]; } # MD5変換(hex形式) return $salt . sha1_hex($salt . $passwd); } #----------------------------------------------------------- # Digest::SHA-1 (hex) 照合 #----------------------------------------------------------- sub decrypt { my ($crypt, $plain) = @_; # saltは先頭の8文字を抜き出す my $salt = substr($crypt, 0, 8); # 照合 return $crypt eq ($salt . sha1_hex($salt . $plain)) ? 1 : 0; }
> 3e24ac81e6ea852cefd4b7d75496dad4a5ab5bead9669e18 > OK
7-4. 暗号/照合コード(Base64出力)
Base64形式出力の場合は、次のように記述することができます。
use strict; # モジュールを宣言 use Digest::SHA1 qw(sha1_base64); # 文字列 my $passwd = '1234'; # 暗号 my $crypt = &encrypt($passwd); print "$crypt\n"; # 照合 if (&decrypt($crypt, $passwd)) { print "OK\n"; } else { print "NG\n"; } #----------------------------------------------------------- # Digest::SHA-1 (Base64) 暗号化 #----------------------------------------------------------- sub encrypt { my $plain = shift; # saltの8文字をアトランダムに生成 my @str = (0 .. 9, 'a' .. 'z', 'A' .. 'Z', '+', '/'); my $salt; for (1 .. 8) { $salt .= $str[int(rand(@str))]; } # MD5変換(hex形式) return $salt . sha1_base64($salt . $passwd); } #----------------------------------------------------------- # Digest::SHA-1 (Base64) 照合 #----------------------------------------------------------- sub decrypt { my ($crypt, $plain) = @_; # saltは先頭の8文字を抜き出す my $salt = substr($crypt, 0, 8); # 照合 return $crypt eq ($salt . sha1_base64($salt . $plain)) ? 1 : 0; }
> +SWsMrVFyRMbrKxsIE6QIlJz62X9wzidvzk > OK