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--FILE--
19<?php
20
21$opsSet = [
22  SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
23  SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE,
24];
25$memSet = [
26  SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE,
27  SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE,
28];
29
30echo 'Argon2 provider: ';
31var_dump(PASSWORD_ARGON2_PROVIDER);
32
33foreach($opsSet as $ops) {
34  foreach($memSet as $mem) {
35    $password = random_bytes(32);
36    echo "Using password: ";
37    var_dump(base64_encode($password));
38    $hash = sodium_crypto_pwhash_str($password, $ops, $mem);
39    echo "Hash: "; var_dump($hash);
40    var_dump(password_verify($password, $hash));
41
42    // And verify that incorrect passwords fail.
43    $password[0] = chr(ord($password[0]) ^ 1);
44    var_dump(password_verify($password, $hash));
45  }
46}
47?>
48--EXPECTF--
49Argon2 provider: string(%d) "%s"
50Using password: string(44) "%s"
51Hash: string(97) "$argon2id$v=19$m=65536,t=2,p=1$%s$%s"
52bool(true)
53bool(false)
54Using password: string(44) "%s"
55Hash: string(98) "$argon2id$v=19$m=262144,t=2,p=1$%s$%s"
56bool(true)
57bool(false)
58Using password: string(44) "%s"
59Hash: string(97) "$argon2id$v=19$m=65536,t=3,p=1$%s$%s"
60bool(true)
61bool(false)
62Using password: string(44) "%s"
63Hash: string(98) "$argon2id$v=19$m=262144,t=3,p=1$%s$%s"
64bool(true)
65bool(false)
66