1--TEST--
2Test interoperability of password_verify()
3--EXTENSIONS--
4sodium
5--SKIPIF--
6<?php
7if (!function_exists('sodium_crypto_pwhash_str')) {
8  echo "skip - No crypto_pwhash_str_verify";
9}
10
11// Depending on library version, libsodium may provide argon2i or argon2id hashes.
12$hash = sodium_crypto_pwhash_str("test", SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE);
13list(, $algo) = explode('$', $hash, 3);
14
15if (!in_array($algo, password_algos(), true /* strict */)) {
16 echo "skip - No $algo support in password_verify()";
17}
18?>
19--FILE--
20<?php
21
22$opsSet = [
23  SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
24  SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE,
25];
26$memSet = [
27  SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE,
28  SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE,
29];
30
31echo 'Argon2 provider: ';
32var_dump(PASSWORD_ARGON2_PROVIDER);
33
34foreach($opsSet as $ops) {
35  foreach($memSet as $mem) {
36    $password = random_bytes(32);
37    echo "Using password: ";
38    var_dump(base64_encode($password));
39    $hash = sodium_crypto_pwhash_str($password, $ops, $mem);
40    echo "Hash: "; var_dump($hash);
41    var_dump(password_verify($password, $hash));
42
43    // And verify that incorrect passwords fail.
44    $password[0] = chr(ord($password[0]) ^ 1);
45    var_dump(password_verify($password, $hash));
46  }
47}
48?>
49--EXPECTF--
50Argon2 provider: string(%d) "%s"
51Using password: string(44) "%s"
52Hash: string(97) "$argon2id$v=19$m=65536,t=2,p=1$%s$%s"
53bool(true)
54bool(false)
55Using password: string(44) "%s"
56Hash: string(98) "$argon2id$v=19$m=262144,t=2,p=1$%s$%s"
57bool(true)
58bool(false)
59Using password: string(44) "%s"
60Hash: string(97) "$argon2id$v=19$m=65536,t=3,p=1$%s$%s"
61bool(true)
62bool(false)
63Using password: string(44) "%s"
64Hash: string(98) "$argon2id$v=19$m=262144,t=3,p=1$%s$%s"
65bool(true)
66bool(false)
67