このサイトについて

みんなのPython Webアプリ編 - ダイジェスト認証

みんなのPython Webアプリ編 - ダイジェスト認証

ダイジェスト認証

BASIC認証はとても手軽な認証方式ですが、大きな欠点があります。ヘッダに埋め込むユーザ名とパスワードを容易に抜き出せるのです。認証情報が可逆的な暗号化方式で暗号化されているため、Webブラウザからサーバに送信されるヘッダをのぞき見ることができれば、たやすくユーザ名とパスワードを抜き出すことができるのです。

この欠点を解消するため、ダイジェスト認証と呼ばれる認証方式が考え出されました。ダイジェスト認証では、ユーザ名やパスワード自体がやりとりされることがありません。ユーザ名やパスワードの代わりに、メッセージダイジェストと呼ばれる一種の「合言葉」を使います。そのため、より安全に認証を行えるわけです。

メッセージダイジェストとハッシュ

メッセージダイジェストにはハッシュを使って認証を行います。ハッシュとは、文字列などのデータから作る値のことを指します。ハッシュを作るための方式は何種類かあって、この方式のことをハッシュ関数と呼びます。また、ハッシュ関数を使って得た値をハッシュ値と呼びます。ハッシュは、Webはもちろんネットワークの世界でとても重要な概念です。

図02 同じデータから作ったハッシュ値は必ず同じになる

図02 同じデータから作ったハッシュ値は必ず同じになる

"ABC"という文字列データを、「A」というハッシュ関数を使ってハッシュ化するとします。すると、いつも同じハッシュ値を得ることができます。逆に、違うデータを与えると、ハッシュ関数はまったく違ったハッシュ値を作ります。

また、ハッシュ値と元の文字列の間にはほとんど関連性がなく、ハッシュ値から元の値を復元することはまず不可能です。

ハッシュ関数にはいくつかの種類があります。よく利用されるのがMD5やSHA-1と呼ばれるハッシュ関数です。Pythonの標準モジュールを使うと、MD5とSHA-1といったハッシュ関数を利用したハッシュを生成できます。

インタラクティブシェルを使ってmd5モジュールを使ってみましょう。new()関数を使い、md5オブジェクトを生成します。その後、hexdigest()メソッドを使い、ハッシュ値を16進数文字列で表示しています。

MD5によるハッシュの作成例

:::python
>>> import md5
>>> m=md5.new('abcde')
>>> print m.hexdigest()
ab56b4d92b40713acc5af89985d4b786

パスワードのような比較的短い文字列だけでなく、ファイルやテストといった長いデータを使ってもハッシュ値を作ることができます。データが少しでも異なるとまったく違ったハッシュ値が出力されます。

このような性質を使うと、ハッシュを認証に利用できるのです。つまり、ハッシュ値を比べるだけで、元のデータが同じかどうかを調べることができるわけです。

ダイジェスト認証の仕組み

ダイジェスト認証が行われる仕組みはBASIC認証とよく似ています。ユーザ名やパスワードそのものに近いデータがやりとりされないこと、セキュリティを保つためにヘッダ上で付加的なデータがやりとりされること、などがBASIC認証と異なります。実際にやりとりされるのはハッシュ値なので、サーバ側にユーザ名やパスワードを保存する必要がないのもダイジェスト認証の特徴の1つです。

ダイジェスト認証は以下のような仕組みで機能します。

1-A)クライアントが認証の必要なパスにリクエストを送る

Webサーバからのリクエストが認証の出発点になります。BASIC認証と同じです。

1-B)サーバが401というステータスのレスポンスを返す

要求されたリクエストに応答するためには認証が必要であることを、Webブラウザに知らせるために特別なステータス番号を送信します。BASIC認証との違いは、ヘッダを使って付加的なデータを送信する点です。

2-A)クライアントがダイアログを表示する

その後、ヘッダにユーザ名やパスワードから作ったハッシュ値を埋め込み、サーバに送信します。実際には、以下のようなヘッダがWebブラウザからサーバに送られます。BASIC認証でBasicとなっていた部分がDigestとなっています。

:::http
Authorization: Digest(ユーザ名やハッシュ値などが続く)

2-B)サーバ側で認証情報を確認し、結果を再送信する

ヘッダのユーザ名、ハッシュなどを評価し、正しい認証情報かどうかを判別します。

2-Aで送信するレスポンスには、ヘッダに以下のような追加の情報が記載されています。nonceとはWebサーバが作るランダムな文字列です。Webサーバは、この文字列を次回のリクエスト時に送信しなければなりません。algorithmでハッシュ関数を指定しています。

:::http
WWW-Authenticate: Digest realm="Secret Zone",
  nonce="Ny8yLzIwMDIgMzoyNjoyNCBQTQ",
  algorithm=MD5, qop="auth"



ダイジェスト認証の継続

Webブラウザを使って一度ダイジェスト認証を行うと、WebブラウザはWebサーバにアクセスするたび、リクエストに認証用のヘッダを追加します。Webサーバ側では、認証用のヘッダを確認できるので、認証状態が継続できます。認証用のヘッダはWebブラウザを終了するまで送り続けられます。ですので、いわゆるログアウトをするためにはWebブラウザを終了するか、認証ダイアログを再度表示してユーザ名と空のパスワードを入力するなどする必要があります。

2014-09-03 15:00