パスワードでページを守ろう ~
ホームページを作る上で、特定の人にだけ見せたいページが出てくるでしょう。
そのようなページでユーザー名とパスワードを入力させる認証ダイアログがポップアップ表示するところを見たことがあると思います。
これを Basic 認証 と呼びます。
ここでは、Basic 認証の仕組みや特徴、.htaccess
と .htpasswd
の書き方、
そして、.htpasswd
に記述するハッシュ化パスワードの生成方法について解説します。
Basic 認証の認証ダイアログは、ブラウザーによって見た目が異なります。
実際に、お使いのブラウザーではどのような画面が出るのかをお試しください。
Basic 認証は、認証の仕組みとしては非常にシンプルなため、手軽に用意できるメリットがある反面、 いくつかのセキュリティ上のデメリットもあります。
通常では漏洩しては困るものが平文で何度もネットワーク上に送信されるのですから、セキュリティという観点から見ると非常に心配になるでしょう。 実際には、認証ダイアログでユーザー名とパスワードを入力してアクセスすると、次のような HTTP リクエストヘッダーがサーバーに送信されます。
GET /lecture/htaccess/secret/ HTTP/1.1
...
Authorization: Basic dGFybzpoaW1pdHN1
...
dGFybzpoaW1pdHN1
ですが、これはユーザー名とパスワードを Base64 でエンコードしたものです。
これをデコードすると次のような結果が得られます。
taro:himitsu
このように、実際にはユーザー名とパスワードが直接的に平文で流れるわけではないのですが、 誰でも復号化できてしまうため、平文で送信されているのと事実上同じと言えます。
このような特性上、Basic 認証を使うなら、通信が暗号化される SSL/TLS で利用すべきでしょう。
Basic 認証は、.htaccess
と .htpasswd
いう名前のテキストファイルに必要事項を
記載して、制限を設けたいディレクトリに接地することで実現します。まずは .htaccess
の書き方を見てみましょう。
以下、各行について説明します。
AuthUserFile
パスワードファイルの指定です。 ここでの指定は、サーバのルートディレクトリからのフルパスで記述しなければいけません。
AuthName
Basic 認証をかける領域名の指定です。 以前はここで指定した領域名がベーシック認証ダイアログに表示されていましたが、 近年ではほとんどのブラウザーで表示されなくなりました。 さほど気にする項目ではありませんが、不自然ではない名前を入れておきましょう。 ただし、日本語のようなマルチバイト文字は避けましょう。
AuthType
認証方式を指定します。Basic 認証であれば Basic
と記述します。
他にはダイジェスト認証というものありますが、ここでは割愛します。
require
何を許可するのかを指定しますが、通常は .htpasswd
に記述した
ユーザーを許可しますので、valid-user
と指定します。
.htpasswd
に記載する情報はユーザー名とパスワードです。
ユーザー名とパスワードは「:
(コロン)」で区切られます。
複数のユーザーを指定する場合には、改行を入れて次の行に記述します。
パスワードは平文ではなく、所定の方法でハッシュ化しておく必要があります。
暗号化は何かしらツールが必要なのですが、.htpasswd
用にハッシュ化ツールを用意しましたのでご活用ください。
後ほど、これを Perl でどのようにして暗号化するのかについて解説します。
パスワードのハッシュ化は UNIX のパスワードのハッシュ化と同じです。
ハッシュ化とは、ある特定のアルゴリズムで別のデータに変換することなのですが、暗号化とは異なり元に戻す (復号化する) ことはできません。
サーバー側では、平文でブラウザーから送信されてきたパスワードを同じアルゴリズムでハッシュ化し、
それが .htpasswd
に記述されたハッシュと一致するかどうかをチェックしています。
こうすることで何がうれしいのかというと、仮にハッシュ化されたパスワードが漏洩したとしても元に戻せませんから安全性が高いということです。 実際には元のパスワードを調べる手法がないわけではありませんが、かなり難しいといえます。
さて、話は元に戻って、Perl でパスワードをハッシュ化するにはどうしたらいいのでしょう。 実は非常に簡単なスクリプトを組むだけで実現できます。前述のハッシュ化ツールのソースコードも紹介します。
ハッシュ化には、Perl のcrypt
関数を使います。crypt
関数の使い方は、以下のとおりです。
crypt(PLAINTEXT, SALT)
PLAINTEXT
の部分はハッシュ化したい文字列です。
SALT
の部分は、大文字・小文字アルファベットと 0 ~ 9 の数字、そして、「.
(ドット)」
「/
(スラッシュ)」のいずれか2文字です。
SALT
は暗号化する際のキーとなるもので、PLAINTEXT
が文字列でも、
SALT
を変えることによってハッシュ値が異なってきます。
つまり同じ PLAINTEXT
に対して、4,096 通りものハッシュ値が生成しうるわけです。
SALT
は固定で決めてしまってもいいのですが、できる限り複雑にするために、
生成するたびにランダムな文字列を指定するのが良いでしょう。
いろいろな方法があるかと思いますが、前述のハッシュ化ツールでは、rand
関数を使ってランダムな 2 文字を抽出します。
以下は前述のハッシュ化ツールのソースコードです。
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = CGI->new;
my $pass = $q->param('pass');
my $encpass = &encrypt_passwd($pass);
print "Content-type: text/plain\n\n";
print $encpass;
exit;
sub encrypt_passwd {
my ($pass) = @_;
my @salt_set = ( 'a' .. 'z', 'A' .. 'Z', '0' .. '9', '.', '/' );
srand;
my $idx1 = int( rand(63) );
my $idx2 = int( rand(63) );
my $salt = $salt_set[$idx1] . $salt_set[$idx2];
return crypt( $pass, $salt );
}