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