Basic 認証に用いる暗号化文字列を Python で作るには

2014年11月28日 22:30

Basic 認証(基本認証とも)は HTTP 通信でよく用いられる認証方式である。Basic 認証が必要なページにリクエストが送られる(アクセスする)と、HTTP サーバは 401 レスポンスコードを返し、認証が必要だということを知らせる。ブラウザにはユーザ名とパスワードを入力するダイアログが表示され、それらが入力されると適宜エンコードされた文字列がサーバに送られる。それがサーバ側であらかじめ設定してある文字列と合致すれば、認証に成功したことになる。まぁかなり端折った解説ではあるが、これが Basic 認証における通信の大まかなやりとりだ。

前述した「サーバであらかじめ設定してある文字列」は大抵の場合、.htpasswd という名前のファイルに収められている。ファイル名は正直なんでもいいが、不可視ファイルにする場合が多いのでドット(.)始まりにするのが通例である。このファイルにはユーザ名とパスワードを暗号化した文字列が1つあるいは複数列記されている。

まぁ形式的な説明はこれぐらいにして、と。Basic 認証で用いる「暗号化した文字列」を生成するには htpasswd コマンドを使う(ファイル名とコマンド名がほとんど同じでややこしいが)。

$ htpasswd -nsb user password
user:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

上記は分かりやすいよう -n オプションを付けて「暗号化した文字列」を標準出力に表示しているが、普通は既存の .htpasswd ファイルのパスを指定するか、-c オプションを付けて新規にファイルを作成する。ちなみに -s オプションは SHA という方式で暗号化するという意味であり、デフォルトの MD5 方式よりはセキュリティレベルは低いが、今回は文字列をサーバ側で動的に生成するという仕様だったので、SHA 指定となっている。

というわけで、Python でこの「暗号化した文字列」を作るには、という話である。ツイート中にもあるように、Python で SHA 暗号化を行なうには hashlib というモジュールを使う。

>>> import hashlib
>>> hashlib.sha1('password').digest()
'[\xaaa\xe4\xc9\xb9??\x06\x82%\x0bl\xf83\x1b~\xe6\x8f\xd8'

上記は password という文字列を SHA(sha1)で暗号化した結果を得る方法である。Basic 認証で用いられる文字列のパスワード部分は、この結果を Base64 エンコードしたものになる。よって、Python で Base64 エンコードまで行なう場合はこうなる。

>>> import hashlib
>>> import base64
>>> base64.b64encode(hashlib.sha1('password').digest())
'W6ph5Mm5Pz8GgiULbPgzG37mj9g='

ユーザ名とコロン、そして {SHA} とこの文字列を繋げれば、前述した htpasswd コマンドの結果と同じものになる。