mikanmarusanのブログ

テクノロジーとかダイビングとか

Argon2id: password hash algorithm which is introduced from PHP7.3

(please find the Japanese translation after the English text)

overview

This is the 3rd article about password hash function on php. I’m deeply in love with password hash function :) . In this article, I’d like to explain the Argon2id which is the password hash algorithm introduced into php7.3 launched on December 6th, 2018.

The following are the previous articles.

mikanmarusan.hatenablog.com
mikanmarusan.hatenablog.com

TL;DR

  • PHP7.3 introduced Argon2id as a password hash algorithm.
  • Argon2id is a hybrid of Argon2i and Argon2d. We should use Argon2id unless there is some particular reason.
  • Default password hash algorithom is NOT changed (bcrypt)

Argon2id

To put it simply, PHP7.3 introduced Argon2id as a password hash algorithm. Argon2id is a hybrid of Argon2i and Argon2d, using a combination of data-depending and data-independent memory accesses, which gives some of Argon2i's resistance to side-channel cache timing attacks and much of Argon2d's resistance to GPU cracking attacks.

There is some question. Why do we use Argon2i if Argon2id exists? Why does not PHP deprecate Argon2i? In RFCs for PHP , it's written as follows:

Should we deprecate Argon2i? [RESOLVED]

No, I do not believe we should deprecate Argon2i from password_*. Argon2i remains a perfectly secure and reasonable choice for password hashing. Argon2id simply provides better resistance to some form of attacks at the cost of time-memory tradeoffs. Argon2id is recommended at this point simply because it provides a blend of Argon2i and Argon2d. The existence of Argon2id does not negate the benefits of Argon2i.

I could not understand :P, then I'd like to deeply explorer.

In RFC draft, it's written as follows:

9.4. Recommendations

The Argon2id variant with t=1 and maximum available memory is recommended as a default setting for all environments. This setting is secure against side-channel attacks and maximizes adversarial costs on dedicated bruteforce hardware.

The draft RFC explicitly telling us that if we don't know which to use, we should pick Argon2id.

  1. Parameter Choice

    If you do not know the difference between them or you consider side-channel attacks as viable threat, choose Argon2id.

APIs

password_hash

Creates a password hash.

string password_hash ( string $password , integer $algo [, array $options ] )

The password_hash() function is altered to accept PASSWORD_ARGON2ID as the algorithm.

<?php
    $raw_passwd = '3kanmarusan_Passw0rd';

    $hashed_passwd = password_hash($raw_passwd, PASSWORD_ARGON2ID);
# generated hash
$argon2id$v=19$m=1024,t=2,p=2$SEJ2M2VNL3B5MXZNN0tDYg$44a3kX0OxiFzoy4bCtkHnAyy7/TVkvIVU7kdyj8ewCg

The password has been hashed using Argon2id since the beginning of hash string is "$argon2id". "$m=1024,t=2,p=2" means cost parameters. These are memory cost, time cost and threads. Argon2id will use the same default cost measures as the Argon2i implementation.

I confirmed the default of password hash algorithm. The default password hash algorithom is NOT changed, PASSWORD_DEFAULT use the bcrypt algorithm.

# confirm the default of password hash algorithm
<?php
  echo "[constants]" . PHP_EOL;
  echo " PASSWORD_BCYRPT: "  . PASSWORD_BCRYPT  . PHP_EOL;
  echo " PASSWORD_ARGON2I: "  . PASSWORD_ARGON2I  . PHP_EOL;
  echo " PASSWORD_ARGON2ID: "  . PASSWORD_ARGON2ID  . PHP_EOL;
  echo " PASSWORD_DEFAULT: " . PASSWORD_DEFAULT . PHP_EOL;
# result
[constants]
 PASSWORD_BCYRPT: 1
 PASSWORD_ARGON2I: 2
 PASSWORD_ARGON2ID: 3
 PASSWORD_DEFAULT: 1

password_verify, password_get_info, password_needs_rehash

The password_verify(), password_get_info() and password_needs_rehash() functions are altered to accept Argon2id hashes.

(Again) TL;DR

  • PHP7.3 introduced Argon2id as a password hash algorithm.
  • Argon2id is a hybrid of Argon2i and Argon2d. We should use Argon2id unless there is some particular reason.
  • Default password hash algorithom is NOT changed (bcrypt)

概要

PHPのパスワードハッシュ関数シリーズの第3弾。自分はどうもパスワードハッシュ関数を愛しているようだ。 2018/12/06にリリースされたPHP7.3で追加されたハッシュアルゴリズム Argon2id を調べてみた。

過去の記事はこちら
mikanmarusan.hatenablog.com
mikanmarusan.hatenablog.com

TL;DR

  • パスワードハッシュ関数(password_*)のハッシュアルゴリズムに Argon2id が追加
  • Argon2idはArdon2iとArgon2idのいいとこどりだが、今後はArgon2idを選ぶのがよさそう
  • PHP7.3でもデフォルトのハッシュアルゴリズムに変更なし(bcyrptのまま)

Argon2id

簡単にまとめると、サイドチャネル攻撃(side-channel timing attacks)耐性があるArgon2iと、GPUのような高性能マシンを使った攻撃に対する耐性があるArgon2dの2つで構成されるパスワードハッシュアルゴリズムである。今回はこのいいとこ取りをしたArgon2idがPHPで採用されたというものである。

ここで疑問が。Argon2idがArgon2dとArgon2iという2つのアルゴリズムがいいとこ取りされるのであれば、PHP7.2で追加されたArgon2iを使う必要はないのではないか?

RFCs for PHPには下記のように書かれていて

Should we deprecate Argon2i? [RESOLVED]

No, I do not believe we should deprecate Argon2i from password_*. Argon2i remains a perfectly secure and reasonable choice for password hashing. Argon2id simply provides better resistance to some form of attacks at the cost of time-memory tradeoffs. Argon2id is recommended at this point simply because it provides a blend of Argon2i and Argon2d. The existence of Argon2id does not negate the benefits of Argon2i.

と、玉虫色の回答が来たのでもう少し深掘り。

アルゴリズムRFC draftにも下記のように書かれている。

9.4. Recommendations

The Argon2id variant with t=1 and maximum available memory is recommended as a default setting for all environments. This setting is secure against side-channel attacks and maximizes adversarial costs on dedicated bruteforce hardware.

もちろん、ユースケースやメモリの量・スレッドの量・必要な計算時間といったコンディションでArgon2iを選んだ方がリーズナブルなケースもあるかもしれないが、Argon2idを選んだ方が得策なようだ。実際、RFCをよく読んで見ると、明示的にArgon2idを選ぶべきという表現もある

  1. Parameter Choice

    If you do not know the difference between them or you consider side-channel attacks as viable threat, choose Argon2id.

API一覧

password_hash

ハッシュ生成関数。

string password_hash ( string $password , integer $algo [, array $options ] )

第1引数 $password は生パスワード、第2引数 $algo はハッシュアルゴリズム定数、第3引数は $options アルゴリズムがサポートするオプションを入力する。ハッシュアルゴリズムをArgon2idをするだけであれば、$algoに PASSWORD_ARGON2ID を指定するだけでよい。

<?php
    $raw_passwd = '3kanmarusan_Passw0rd';

    $hashed_passwd = password_hash($raw_passwd, PASSWORD_ARGON2ID);
# 生成されたハッシュ
$argon2id$v=19$m=1024,t=2,p=2$SEJ2M2VNL3B5MXZNN0tDYg$44a3kX0OxiFzoy4bCtkHnAyy7/TVkvIVU7kdyj8ewCg

$argon2idで始まっているので、Argon2idっぽい。$m=1024,t=2,p=2がハッシュ化時に使用しているパラメータ。これはPHPで定義されたデフォルト値そのものである(前述)。ハッシュアルゴリズムが使うメモリコスト(メモリ使用量)と時間コスト(回数)と並列度(ハッシュ化時に利用するCPUスレッドの数)をパラメータはArgon2iの時と同じである。

ちなみに、ハッシュアルゴリズムのデフォルト(PASSWORD_DEFAULT)に変更があるか調べたところ、PHP7.3の段階でも変更がないようだ。

# PASSWORD_DEFAULTはまだbcryptということを調べる
<?php
  echo "[constants]" . PHP_EOL;
  echo " PASSWORD_BCYRPT: "  . PASSWORD_BCRYPT  . PHP_EOL;
  echo " PASSWORD_ARGON2I: "  . PASSWORD_ARGON2I  . PHP_EOL;
  echo " PASSWORD_ARGON2ID: "  . PASSWORD_ARGON2ID  . PHP_EOL;
  echo " PASSWORD_DEFAULT: " . PASSWORD_DEFAULT . PHP_EOL;
# 実行結果
[constants]
 PASSWORD_BCYRPT: 1
 PASSWORD_ARGON2I: 2
 PASSWORD_ARGON2ID: 3
 PASSWORD_DEFAULT: 1

password_verify, password_get_info, password_needs_rehash

ここは変更なし

(再掲)TL;DR

  • パスワードハッシュ関数(password_*)のハッシュアルゴリズムに Argon2id が追加
  • Argon2idはArdon2iとArgon2idのいいとこどりだが、今後はArgon2idを選ぶのがよさそう
  • PHP7.3でもデフォルトのハッシュアルゴリズムに変更なし(bcyrptのまま)