mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Merge branch 'PHP-7.4'
* PHP-7.4: Provide argon2i(d) password hashing from sodium when needed
This commit is contained in:
commit
17bfac6347
@ -11,6 +11,6 @@ if test "$PHP_SODIUM" != "no"; then
|
||||
|
||||
AC_DEFINE(HAVE_LIBSODIUMLIB, 1, [ ])
|
||||
|
||||
PHP_NEW_EXTENSION(sodium, libsodium.c, $ext_shared)
|
||||
PHP_NEW_EXTENSION(sodium, libsodium.c sodium_pwhash.c, $ext_shared)
|
||||
PHP_SUBST(SODIUM_SHARED_LIBADD)
|
||||
fi
|
||||
|
@ -4,7 +4,7 @@ ARG_WITH("sodium", "for libsodium support", "no");
|
||||
|
||||
if (PHP_SODIUM != "no") {
|
||||
if (CHECK_LIB("libsodium.lib", "sodium", PHP_SODIUM) && CHECK_HEADER_ADD_INCLUDE("sodium.h", "CFLAGS_SODIUM")) {
|
||||
EXTENSION("sodium", "libsodium.c");
|
||||
EXTENSION("sodium", "libsodium.c sodium_pwhash.c");
|
||||
AC_DEFINE('HAVE_LIBSODIUMLIB', 1 , 'Have the Sodium library');
|
||||
AC_DEFINE("HAVE_CRYPTO_AEAD_AES256GCM", 1, "");
|
||||
PHP_INSTALL_HEADERS("ext/sodium/", "php_libsodium.h");
|
||||
|
@ -358,8 +358,18 @@ static const zend_function_entry sodium_functions[] = {
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
/* Load after the "standard" module in order to give it
|
||||
* priority in registering argon2i/argon2id password hashers.
|
||||
*/
|
||||
static const zend_module_dep sodium_deps[] = {
|
||||
ZEND_MOD_REQUIRED("standard")
|
||||
ZEND_MOD_END
|
||||
};
|
||||
|
||||
zend_module_entry sodium_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
STANDARD_MODULE_HEADER_EX,
|
||||
NULL,
|
||||
sodium_deps,
|
||||
"sodium",
|
||||
sodium_functions,
|
||||
PHP_MINIT(sodium),
|
||||
@ -632,6 +642,13 @@ PHP_MINIT_FUNCTION(sodium)
|
||||
REGISTER_LONG_CONSTANT("SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING",
|
||||
sodium_base64_VARIANT_URLSAFE_NO_PADDING, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
|
||||
#if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
|
||||
if (FAILURE == PHP_MINIT(sodium_password_hash)(INIT_FUNC_ARGS_PASSTHRU)) {
|
||||
return FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ extern zend_module_entry sodium_module_entry;
|
||||
#endif
|
||||
|
||||
PHP_MINIT_FUNCTION(sodium);
|
||||
PHP_MINIT_FUNCTION(sodium_password_hash);
|
||||
PHP_MSHUTDOWN_FUNCTION(sodium);
|
||||
PHP_RINIT_FUNCTION(sodium);
|
||||
PHP_RSHUTDOWN_FUNCTION(sodium);
|
||||
|
215
ext/sodium/sodium_pwhash.c
Normal file
215
ext/sodium/sodium_pwhash.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Sara Golemon <pollita@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_libsodium.h"
|
||||
#include "ext/standard/php_password.h"
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6)
|
||||
|
||||
/**
|
||||
* OPSLIMIT and MEMLIMIT are taken from libsodium's MODERATE values.
|
||||
* MEMLIMIT is normalized to KB even though sodium uses Bytes in order to
|
||||
* present a consistent user-facing API.
|
||||
*
|
||||
* Threads are fixed at 1 by libsodium.
|
||||
*
|
||||
* When updating these values, synchronize ext/standard/php_password.h values.
|
||||
*/
|
||||
#define PHP_SODIUM_PWHASH_MEMLIMIT (256 << 10)
|
||||
#define PHP_SODIUM_PWHASH_OPSLIMIT 3
|
||||
#define PHP_SODIUM_PWHASH_THREADS 1
|
||||
|
||||
static zend_string *php_sodium_argon2_hash(const zend_string *password, zend_array *options, int alg) {
|
||||
size_t opslimit = PHP_SODIUM_PWHASH_OPSLIMIT;
|
||||
size_t memlimit = PHP_SODIUM_PWHASH_MEMLIMIT;
|
||||
zend_string *ret;
|
||||
|
||||
if ((ZSTR_LEN(password) >= 0xffffffff)) {
|
||||
php_error_docref(NULL, E_WARNING, "Password is too long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (options) {
|
||||
zval *opt;
|
||||
if ((opt = zend_hash_str_find(options, "memory_cost", strlen("memory_cost")))) {
|
||||
memlimit = zval_get_long(opt);
|
||||
if ((memlimit < crypto_pwhash_MEMLIMIT_MIN) || (memlimit > crypto_pwhash_MEMLIMIT_MAX)) {
|
||||
php_error_docref(NULL, E_WARNING, "Memory cost is outside of allowed memory range");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if ((opt = zend_hash_str_find(options, "time_cost", strlen("time_cost")))) {
|
||||
opslimit = zval_get_long(opt);
|
||||
if ((opslimit < crypto_pwhash_OPSLIMIT_MIN) || (opslimit > crypto_pwhash_OPSLIMIT_MAX)) {
|
||||
php_error_docref(NULL, E_WARNING, "Time cost is outside of allowed time range");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if ((opt = zend_hash_str_find(options, "threads", strlen("threads"))) && (zval_get_long(opt) != 1)) {
|
||||
php_error_docref(NULL, E_WARNING, "A thread value other than 1 is not supported by this implementation");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = zend_string_alloc(crypto_pwhash_STRBYTES - 1, 0);
|
||||
if (crypto_pwhash_str_alg(ZSTR_VAL(ret), ZSTR_VAL(password), ZSTR_LEN(password), opslimit, memlimit << 10, alg)) {
|
||||
php_error_docref(NULL, E_WARNING, "Unexpected failure hashing password");
|
||||
zend_string_release(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZSTR_LEN(ret) = strlen(ZSTR_VAL(ret));
|
||||
ZSTR_VAL(ret)[ZSTR_LEN(ret)] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_bool php_sodium_argon2_verify(const zend_string *password, const zend_string *hash) {
|
||||
if ((ZSTR_LEN(password) >= 0xffffffff) || (ZSTR_LEN(hash) >= 0xffffffff)) {
|
||||
return 0;
|
||||
}
|
||||
return crypto_pwhash_str_verify(ZSTR_VAL(hash), ZSTR_VAL(password), ZSTR_LEN(password)) == 0;
|
||||
}
|
||||
|
||||
static zend_bool php_sodium_argon2_needs_rehash(const zend_string *hash, zend_array *options) {
|
||||
size_t opslimit = PHP_SODIUM_PWHASH_OPSLIMIT;
|
||||
size_t memlimit = PHP_SODIUM_PWHASH_MEMLIMIT;
|
||||
|
||||
if (options) {
|
||||
zval *opt;
|
||||
if ((opt = zend_hash_str_find(options, "memory_cost", strlen("memory_cost")))) {
|
||||
memlimit = zval_get_long(opt);
|
||||
if ((memlimit < crypto_pwhash_MEMLIMIT_MIN) || (memlimit > crypto_pwhash_MEMLIMIT_MAX)) {
|
||||
php_error_docref(NULL, E_WARNING, "Memory cost is outside of allowed memory range");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((opt = zend_hash_str_find(options, "time_cost", strlen("time_cost")))) {
|
||||
opslimit = zval_get_long(opt);
|
||||
if ((opslimit < crypto_pwhash_OPSLIMIT_MIN) || (opslimit > crypto_pwhash_OPSLIMIT_MAX)) {
|
||||
php_error_docref(NULL, E_WARNING, "Time cost is outside of allowed time range");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((opt = zend_hash_str_find(options, "threads", strlen("threads"))) && (zval_get_long(opt) != 1)) {
|
||||
php_error_docref(NULL, E_WARNING, "A thread value other than 1 is not supported by this implementation");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return crypto_pwhash_str_needs_rehash(ZSTR_VAL(hash), opslimit, memlimit << 10);
|
||||
}
|
||||
|
||||
static int php_sodium_argon2_get_info(zval *return_value, const zend_string *hash) {
|
||||
const char* p = NULL;
|
||||
zend_long v = 0, threads = 1;
|
||||
zend_long memory_cost = PHP_SODIUM_PWHASH_MEMLIMIT;
|
||||
zend_long time_cost = PHP_SODIUM_PWHASH_OPSLIMIT;
|
||||
|
||||
if (!hash || (ZSTR_LEN(hash) < sizeof("$argon2id$"))) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
p = ZSTR_VAL(hash);
|
||||
if (!memcmp(p, "$argon2i$", strlen("$argon2i$"))) {
|
||||
p += strlen("$argon2i$");
|
||||
} else if (!memcmp(p, "$argon2id$", strlen("$argon2id$"))) {
|
||||
p += strlen("$argon2id$");
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
sscanf(p, "v=" ZEND_LONG_FMT "$m=" ZEND_LONG_FMT ",t=" ZEND_LONG_FMT ",p=" ZEND_LONG_FMT,
|
||||
&v, &memory_cost, &time_cost, &threads);
|
||||
|
||||
add_assoc_long(return_value, "memory_cost", memory_cost);
|
||||
add_assoc_long(return_value, "time_cost", time_cost);
|
||||
add_assoc_long(return_value, "threads", threads);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* argon2i specific methods */
|
||||
|
||||
static zend_string *php_sodium_argon2i_hash(const zend_string *password, zend_array *options) {
|
||||
return php_sodium_argon2_hash(password, options, crypto_pwhash_ALG_ARGON2I13);
|
||||
}
|
||||
|
||||
static const php_password_algo sodium_algo_argon2i = {
|
||||
"argon2i",
|
||||
php_sodium_argon2i_hash,
|
||||
php_sodium_argon2_verify,
|
||||
php_sodium_argon2_needs_rehash,
|
||||
php_sodium_argon2_get_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* argon2id specific methods */
|
||||
|
||||
static zend_string *php_sodium_argon2id_hash(const zend_string *password, zend_array *options) {
|
||||
return php_sodium_argon2_hash(password, options, crypto_pwhash_ALG_ARGON2ID13);
|
||||
}
|
||||
|
||||
static const php_password_algo sodium_algo_argon2id = {
|
||||
"argon2id",
|
||||
php_sodium_argon2id_hash,
|
||||
php_sodium_argon2_verify,
|
||||
php_sodium_argon2_needs_rehash,
|
||||
php_sodium_argon2_get_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
PHP_MINIT_FUNCTION(sodium_password_hash) /* {{{ */ {
|
||||
zend_string *argon2i = zend_string_init("argon2i", strlen("argon2i"), 1);
|
||||
|
||||
if (php_password_algo_find(argon2i)) {
|
||||
/* Nothing to do. Core has registered these algorithms for us. */
|
||||
zend_string_release(argon2i);
|
||||
return SUCCESS;
|
||||
}
|
||||
zend_string_release(argon2i);
|
||||
|
||||
if (FAILURE == php_password_algo_register("argon2i", &sodium_algo_argon2i)) {
|
||||
return FAILURE;
|
||||
}
|
||||
REGISTER_STRING_CONSTANT("PASSWORD_ARGON2I", "argon2i", CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
if (FAILURE == php_password_algo_register("argon2id", &sodium_algo_argon2id)) {
|
||||
return FAILURE;
|
||||
}
|
||||
REGISTER_STRING_CONSTANT("PASSWORD_ARGON2ID", "argon2id", CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_MEMORY_COST", PHP_SODIUM_PWHASH_MEMLIMIT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_TIME_COST", PHP_SODIUM_PWHASH_OPSLIMIT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_THREADS", PHP_SODIUM_PWHASH_THREADS, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
REGISTER_STRING_CONSTANT("PASSWORD_ARGON2_PROVIDER", "sodium", CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#endif /* HAVE_SODIUM_PASSWORD_HASH */
|
@ -11,102 +11,63 @@ if (!in_array('argon2i', password_algos(), true /* strict */)) {
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo 'Argon2 provider: ';
|
||||
var_dump(PASSWORD_ARGON2_PROVIDER);
|
||||
|
||||
foreach([1, 2, 4] as $mem) {
|
||||
foreach([1, 2, 4] as $time) {
|
||||
foreach([1, 2, 4] as $threads) {
|
||||
$opts = [
|
||||
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST * $mem,
|
||||
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST * $time,
|
||||
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS * $threads,
|
||||
];
|
||||
$password = random_bytes(32);
|
||||
echo "Using password: ";
|
||||
var_dump(base64_encode($password));
|
||||
$hash = password_hash($password, 'argon2i', $opts);
|
||||
echo "Hash: "; var_dump($hash);
|
||||
var_dump(sodium_crypto_pwhash_str_verify($hash, $password));
|
||||
}
|
||||
$opts = [
|
||||
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST * $mem,
|
||||
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST * $time,
|
||||
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS,
|
||||
];
|
||||
$password = random_bytes(32);
|
||||
echo "Using password: ";
|
||||
var_dump(base64_encode($password));
|
||||
$hash = password_hash($password, 'argon2i', $opts);
|
||||
echo "Hash: "; var_dump($hash);
|
||||
var_dump(sodium_crypto_pwhash_str_verify($hash, $password));
|
||||
|
||||
// And verify that incorrect passwords fail.
|
||||
$password[0] = chr(ord($password[0]) ^ 1);
|
||||
var_dump(sodium_crypto_pwhash_str_verify($hash, $password));
|
||||
}
|
||||
}
|
||||
--EXPECTF--
|
||||
Argon2 provider: string(%d) "%s"
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=1024,t=3,p=2$%s"
|
||||
Hash: string(97) "$argon2i$v=19$m=262144,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=1024,t=3,p=4$%s"
|
||||
Hash: string(97) "$argon2i$v=19$m=262144,t=6,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=1024,t=3,p=8$%s"
|
||||
Hash: string(98) "$argon2i$v=19$m=262144,t=12,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=1024,t=6,p=2$%s"
|
||||
Hash: string(97) "$argon2i$v=19$m=524288,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=1024,t=6,p=4$%s"
|
||||
Hash: string(97) "$argon2i$v=19$m=524288,t=6,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=1024,t=6,p=8$%s"
|
||||
Hash: string(98) "$argon2i$v=19$m=524288,t=12,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=1024,t=12,p=2$%s"
|
||||
Hash: string(98) "$argon2i$v=19$m=1048576,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=1024,t=12,p=4$%s"
|
||||
Hash: string(98) "$argon2i$v=19$m=1048576,t=6,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=1024,t=12,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=2048,t=3,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=2048,t=3,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=2048,t=3,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=2048,t=6,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=2048,t=6,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=2048,t=6,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=2048,t=12,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=2048,t=12,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=2048,t=12,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=4096,t=3,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=4096,t=3,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=4096,t=3,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=4096,t=6,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=4096,t=6,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(95) "$argon2i$v=19$m=4096,t=6,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=4096,t=12,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=4096,t=12,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2i$v=19$m=4096,t=12,p=8$%s"
|
||||
Hash: string(99) "$argon2i$v=19$m=1048576,t=12,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
@ -11,102 +11,63 @@ if (!in_array('argon2id', password_algos(), true /* strict */)) {
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo 'Argon2 provider: ';
|
||||
var_dump(PASSWORD_ARGON2_PROVIDER);
|
||||
|
||||
foreach([1, 2, 4] as $mem) {
|
||||
foreach([1, 2, 4] as $time) {
|
||||
foreach([1, 2, 4] as $threads) {
|
||||
$opts = [
|
||||
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST * $mem,
|
||||
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST * $time,
|
||||
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS * $threads,
|
||||
];
|
||||
$password = random_bytes(32);
|
||||
echo "Using password: ";
|
||||
var_dump(base64_encode($password));
|
||||
$hash = password_hash($password, 'argon2id', $opts);
|
||||
echo "Hash: "; var_dump($hash);
|
||||
var_dump(sodium_crypto_pwhash_str_verify($hash, $password));
|
||||
}
|
||||
$opts = [
|
||||
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST * $mem,
|
||||
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST * $time,
|
||||
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS,
|
||||
];
|
||||
$password = random_bytes(32);
|
||||
echo "Using password: ";
|
||||
var_dump(base64_encode($password));
|
||||
$hash = password_hash($password, 'argon2id', $opts);
|
||||
echo "Hash: "; var_dump($hash);
|
||||
var_dump(sodium_crypto_pwhash_str_verify($hash, $password));
|
||||
|
||||
// And verify that incorrect passwords fail.
|
||||
$password[0] = chr(ord($password[0]) ^ 1);
|
||||
var_dump(sodium_crypto_pwhash_str_verify($hash, $password));
|
||||
}
|
||||
}
|
||||
--EXPECTF--
|
||||
Argon2 provider: string(%d) "%s"
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=1024,t=3,p=2$%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=262144,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=1024,t=3,p=4$%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=262144,t=6,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=1024,t=3,p=8$%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=262144,t=12,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=1024,t=6,p=2$%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=524288,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=1024,t=6,p=4$%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=524288,t=6,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=1024,t=6,p=8$%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=524288,t=12,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=1024,t=12,p=2$%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=1048576,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=1024,t=12,p=4$%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=1048576,t=6,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=1024,t=12,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=2048,t=3,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=2048,t=3,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=2048,t=3,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=2048,t=6,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=2048,t=6,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=2048,t=6,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=2048,t=12,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=2048,t=12,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=2048,t=12,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=4096,t=3,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=4096,t=3,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=4096,t=3,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=4096,t=6,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=4096,t=6,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(96) "$argon2id$v=19$m=4096,t=6,p=8$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=4096,t=12,p=2$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=4096,t=12,p=4$%s"
|
||||
bool(true)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=4096,t=12,p=8$%s"
|
||||
Hash: string(100) "$argon2id$v=19$m=1048576,t=12,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
@ -27,6 +27,9 @@ $memSet = [
|
||||
SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE,
|
||||
];
|
||||
|
||||
echo 'Argon2 provider: ';
|
||||
var_dump(PASSWORD_ARGON2_PROVIDER);
|
||||
|
||||
foreach($opsSet as $ops) {
|
||||
foreach($memSet as $mem) {
|
||||
$password = random_bytes(32);
|
||||
@ -35,33 +38,47 @@ foreach($opsSet as $ops) {
|
||||
$hash = sodium_crypto_pwhash_str($password, $ops, $mem);
|
||||
echo "Hash: "; var_dump($hash);
|
||||
var_dump(password_verify($password, $hash));
|
||||
|
||||
// And verify that incorrect passwords fail.
|
||||
$password[0] = chr(ord($password[0]) ^ 1);
|
||||
var_dump(password_verify($password, $hash));
|
||||
}
|
||||
}
|
||||
--EXPECTF--
|
||||
Argon2 provider: string(%d) "%s"
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=65536,t=2,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=262144,t=2,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=1048576,t=2,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=65536,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=262144,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=1048576,t=3,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(97) "$argon2id$v=19$m=65536,t=4,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(98) "$argon2id$v=19$m=262144,t=4,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
Using password: string(44) "%s"
|
||||
Hash: string(%d) "$argon2i%s"
|
||||
Hash: string(99) "$argon2id$v=19$m=1048576,t=4,p=1$%s$%s"
|
||||
bool(true)
|
||||
bool(false)
|
||||
|
@ -450,6 +450,8 @@ PHP_MINIT_FUNCTION(password) /* {{{ */
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_MEMORY_COST", PHP_PASSWORD_ARGON2_MEMORY_COST, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_TIME_COST", PHP_PASSWORD_ARGON2_TIME_COST, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_THREADS", PHP_PASSWORD_ARGON2_THREADS, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
REGISTER_STRING_CONSTANT("PASSWORD_ARGON2_PROVIDER", "standard", CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
|
@ -33,9 +33,16 @@ PHP_MSHUTDOWN_FUNCTION(password);
|
||||
#define PHP_PASSWORD_BCRYPT_COST 10
|
||||
|
||||
#if HAVE_ARGON2LIB
|
||||
#define PHP_PASSWORD_ARGON2_MEMORY_COST 1<<10
|
||||
/**
|
||||
* OPSLIMIT and MEMLIMIT are taken from libsodium's MODERATE values.
|
||||
* Threads are fixed at 1 by libsodium.
|
||||
*
|
||||
* When updating these values, synchronize ext/sodium/sodium_pwhash.c values.
|
||||
* Note that libargon expresses memlimit in KB, while libsoidum uses bytes.
|
||||
*/
|
||||
#define PHP_PASSWORD_ARGON2_MEMORY_COST (256 << 10)
|
||||
#define PHP_PASSWORD_ARGON2_TIME_COST 3
|
||||
#define PHP_PASSWORD_ARGON2_THREADS 2
|
||||
#define PHP_PASSWORD_ARGON2_THREADS 1
|
||||
#endif
|
||||
|
||||
typedef struct _php_password_algo {
|
||||
|
Loading…
Reference in New Issue
Block a user