Posted at

PHP で生成したパスワードハッシュが Python でマッチするか確認

More than 1 year has passed since last update.


環境

PHP 7.1

Python 2.7.6


確認したいこと

現在、PHP で新規開発をしていて、パスワードの暗号化に password_hash を使用している。

かなり先のことだが、将来的に別の言語(ここでは Python)に移行した際に、暗号化したパスワードが同じように使えるのか疑問:question:

つまり、 Python に移行してもユーザーのパスワードの照合が正常にできて、ログインできることを確認したい。

もう少しミクロな言い方をすると、 password_hash は Blowfish という暗号化アルゴリズムを使用しているので(後述)、Python でも Blowfish が使えて照合できるかを確認したい。


PHP で暗号化する

password_hash('password', PASSWORD_DEFAULT);

// $2y$10$BN2hH0B3gnZceNlW1JXiNOUN8NWybLlfqZh6WQ/imah4htM8fktFW

password_hash('password', PASSWORD_BCRYPT);
// $2y$10$CuZkO0N29B1YtHHI9mwvIOCSUitQh4ptyfxYWvHhHoHHP2GZqC5Ga


解説

password_hash では現在、PASSWORD_DEFAULT と PASSWORD_BCRYPT という 2 種類の定数を指定できる。

http://php.net/manual/ja/function.password-hash.php


定数の中身を確認してみた(スタブだけど)


/php/lib/php.jar!/stubs/standard/password.php

define("PASSWORD_DEFAULT", 1);

define("PASSWORD_BCRYPT", 1);

結局 PASSWORD_DEFAULT も PASSWORD_BCRYPT も同じ値を指している。

この場合、Bcrypt での実装になる。

Bcrypt ≒ Blowfish なので、現在の password_hash の暗号化アルゴリズムは必ず Blowfish になるもよう。

※ Bcrypt の解説はここが分かりやすかった

https://goo.gl/kpS5En

※他の暗号化アルゴリズムを使いたかったら Crypt を使えばできそう

http://php.net/manual/ja/function.crypt.php


Python で照合できるか確認

import bcrypt

password = b'password'
phpHash = '$2y$10$BN2hH0B3gnZceNlW1JXiNOUN8NWybLlfqZh6WQ/imah4htM8fktFW'

if bcrypt.checkpw(password, phpHash):
print("It Matches!")
else:
print("It Does not Match :(")

# It Matches!

無事にマッチした :ok_woman_tone1:


解説


  • bcrypt モジュールを用いて、PHP で暗号化したパスワードがマッチするか確認している




マメ知識(知らなかっただけ)

PHP の password_hash を用いて生成した値の暗号化バージョン(1番左の部分)は $2y$ になる。

しかし Python の bcrypt モジュールを用いて生成する場合、暗号化バージョンは $2a$$2b$ のみしか指定できないもよう。

salt = bcrypt.gensalt(rounds=10, prefix=b'2a')

password = b'password'
hashed = bcrypt.hashpw(password, salt)

prefix の部分

これでは同じパスワードとみなしてくれないのでは?:rolling_eyes: と思ったが、上述の通りマッチした。

逆に bcrypt.hashpw で生成した値を password_verify で照合しても無事にマッチした。

つまり、暗号化バージョンが $2a$$2y$ のように異なっていても同じパスワードとして認識してくれるので、将来的に Python に移行した際にわざわざ $2y$$2a$ に置換するなどの処理は不要。