mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
Merge branch 'pull-request/1997'
This commit is contained in:
commit
1305fdaa3b
@ -550,6 +550,38 @@ dnl Check for getrandom on newer Linux kernels
|
||||
dnl
|
||||
AC_CHECK_DECLS([getrandom])
|
||||
|
||||
dnl
|
||||
dnl Check for argon2
|
||||
dnl
|
||||
PHP_ARG_WITH(password-argon2, for Argon2 support,
|
||||
[ --with-password-argon2[=DIR] Include Argon2 support in password_*. DIR is the Argon2 shared library path]])
|
||||
|
||||
if test "$PHP_PASSWORD_ARGON2" != "no"; then
|
||||
AC_MSG_CHECKING([for Argon2 library])
|
||||
for i in $PHP_PASSWORD_ARGON2 /usr /usr/local ; do
|
||||
if test -r $i/include/argon2.h; then
|
||||
ARGON2_DIR=$i;
|
||||
AC_MSG_RESULT(found in $i)
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if test -z "$ARGON2_DIR"; then
|
||||
AC_MSG_RESULT([not found])
|
||||
AC_MSG_ERROR([Please ensure the argon2 header and library are installed])
|
||||
fi
|
||||
|
||||
PHP_ADD_LIBRARY_WITH_PATH(argon2, $ARGON2_DIR/$PHP_LIBDIR)
|
||||
PHP_ADD_INCLUDE($ARGON2_DIR/include)
|
||||
|
||||
AC_CHECK_LIB(argon2, argon2_hash, [
|
||||
LIBS="$LIBS -largon2"
|
||||
AC_DEFINE(HAVE_ARGON2LIB, 1, [ Define to 1 if you have the <argon2.h> header file ])
|
||||
], [
|
||||
AC_MSG_ERROR([Problem with libargon2.(a|so). Please verify that Argon2 header and libaries are installed])
|
||||
])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Setup extension sources
|
||||
dnl
|
||||
|
@ -1,6 +1,17 @@
|
||||
// vim:ft=javascript
|
||||
// $Id$
|
||||
|
||||
ARG_WITH("password-argon2", "Argon2 support", "no");
|
||||
|
||||
if (PHP_PASSWORD_ARGON2 != "no") {
|
||||
if (CHECK_LIB("Argon2Ref.lib", null, PHP_PASSWORD_ARGON2)
|
||||
&& CHECK_HEADER_ADD_INCLUDE("argon2.h", "CFLAGS")) {
|
||||
AC_DEFINE('HAVE_ARGON2LIB', 1);
|
||||
} else {
|
||||
WARNING("Argon2 not enabled; libaries and headers not found");
|
||||
}
|
||||
}
|
||||
|
||||
ARG_WITH("config-file-scan-dir", "Dir to check for additional php ini files", "");
|
||||
|
||||
AC_DEFINE("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR);
|
||||
|
@ -13,6 +13,7 @@
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Anthony Ferrara <ircmaxell@php.net> |
|
||||
| Charles R. Portwood II <charlesportwoodii@erianna.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
@ -30,6 +31,9 @@
|
||||
#include "zend_interfaces.h"
|
||||
#include "info.h"
|
||||
#include "php_random.h"
|
||||
#if HAVE_ARGON2LIB
|
||||
#include "argon2.h"
|
||||
#endif
|
||||
|
||||
#if PHP_WIN32
|
||||
#include "win32/winutil.h"
|
||||
@ -39,8 +43,16 @@ PHP_MINIT_FUNCTION(password) /* {{{ */
|
||||
{
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_DEFAULT", PHP_PASSWORD_DEFAULT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_BCRYPT", PHP_PASSWORD_BCRYPT, CONST_CS | CONST_PERSISTENT);
|
||||
#if HAVE_ARGON2LIB
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_ARGON2I", PHP_PASSWORD_ARGON2I, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
|
||||
REGISTER_LONG_CONSTANT("PASSWORD_BCRYPT_DEFAULT_COST", PHP_PASSWORD_BCRYPT_COST, CONST_CS | CONST_PERSISTENT);
|
||||
#if HAVE_ARGON2LIB
|
||||
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);
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -51,6 +63,10 @@ static char* php_password_get_algo_name(const php_password_algo algo)
|
||||
switch (algo) {
|
||||
case PHP_PASSWORD_BCRYPT:
|
||||
return "bcrypt";
|
||||
#if HAVE_ARGON2LIB
|
||||
case PHP_PASSWORD_ARGON2I:
|
||||
return "argon2i";
|
||||
#endif
|
||||
case PHP_PASSWORD_UNKNOWN:
|
||||
default:
|
||||
return "unknown";
|
||||
@ -62,6 +78,11 @@ static php_password_algo php_password_determine_algo(const char *hash, const siz
|
||||
if (len > 3 && hash[0] == '$' && hash[1] == '2' && hash[2] == 'y' && len == 60) {
|
||||
return PHP_PASSWORD_BCRYPT;
|
||||
}
|
||||
#if HAVE_ARGON2LIB
|
||||
if (len >= sizeof("$argon2i$")-1 && !memcmp(hash, "$argon2i$", sizeof("$argon2i$")-1)) {
|
||||
return PHP_PASSWORD_ARGON2I;
|
||||
}
|
||||
#endif
|
||||
|
||||
return PHP_PASSWORD_UNKNOWN;
|
||||
}
|
||||
@ -143,6 +164,8 @@ static int php_password_make_salt(size_t length, char *ret) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array password_get_info(string $hash)
|
||||
Retrieves information about a given hash */
|
||||
PHP_FUNCTION(password_get_info)
|
||||
{
|
||||
php_password_algo algo;
|
||||
@ -167,6 +190,21 @@ PHP_FUNCTION(password_get_info)
|
||||
add_assoc_long(&options, "cost", cost);
|
||||
}
|
||||
break;
|
||||
#if HAVE_ARGON2LIB
|
||||
case PHP_PASSWORD_ARGON2I:
|
||||
{
|
||||
zend_long v = 0;
|
||||
zend_long memory_cost = PHP_PASSWORD_ARGON2_MEMORY_COST;
|
||||
zend_long time_cost = PHP_PASSWORD_ARGON2_TIME_COST;
|
||||
zend_long threads = PHP_PASSWORD_ARGON2_THREADS;
|
||||
|
||||
sscanf(hash, "$%*[argon2i]$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(&options, "memory_cost", memory_cost);
|
||||
add_assoc_long(&options, "time_cost", time_cost);
|
||||
add_assoc_long(&options, "threads", threads);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case PHP_PASSWORD_UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
@ -178,7 +216,10 @@ PHP_FUNCTION(password_get_info)
|
||||
add_assoc_string(return_value, "algoName", algo_name);
|
||||
add_assoc_zval(return_value, "options", &options);
|
||||
}
|
||||
/** }}} */
|
||||
|
||||
/* {{{ proto boolean password_needs_rehash(string $hash, integer $algo[, array $options])
|
||||
Determines if a given hash requires re-hashing based upon parameters */
|
||||
PHP_FUNCTION(password_needs_rehash)
|
||||
{
|
||||
zend_long new_algo = 0;
|
||||
@ -213,14 +254,43 @@ PHP_FUNCTION(password_needs_rehash)
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if HAVE_ARGON2LIB
|
||||
case PHP_PASSWORD_ARGON2I:
|
||||
{
|
||||
zend_long v = 0;
|
||||
zend_long new_memory_cost = PHP_PASSWORD_ARGON2_MEMORY_COST, memory_cost = 0;
|
||||
zend_long new_time_cost = PHP_PASSWORD_ARGON2_TIME_COST, time_cost = 0;
|
||||
zend_long new_threads = PHP_PASSWORD_ARGON2_THREADS, threads = 0;
|
||||
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "memory_cost", sizeof("memory_cost")-1)) != NULL) {
|
||||
new_memory_cost = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "time_cost", sizeof("time_cost")-1)) != NULL) {
|
||||
new_time_cost = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "threads", sizeof("threads")-1)) != NULL) {
|
||||
new_threads = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
sscanf(hash, "$%*[argon2i]$v=" ZEND_LONG_FMT "$m=" ZEND_LONG_FMT ",t=" ZEND_LONG_FMT ",p=" ZEND_LONG_FMT, &v, &memory_cost, &time_cost, &threads);
|
||||
|
||||
if (new_time_cost != time_cost || new_memory_cost != memory_cost || new_threads != threads) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case PHP_PASSWORD_UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto boolean password_make_salt(string password, string hash)
|
||||
/* {{{ proto boolean password_verify(string password, string hash)
|
||||
Verify a hash created using crypt() or password_hash() */
|
||||
PHP_FUNCTION(password_verify)
|
||||
{
|
||||
@ -228,35 +298,62 @@ PHP_FUNCTION(password_verify)
|
||||
size_t i, password_len, hash_len;
|
||||
char *password, *hash;
|
||||
zend_string *ret;
|
||||
php_password_algo algo;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &password, &password_len, &hash, &hash_len) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if ((ret = php_crypt(password, (int)password_len, hash, (int)hash_len, 1)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
|
||||
algo = php_password_determine_algo(hash, (size_t) hash_len);
|
||||
|
||||
switch(algo) {
|
||||
#if HAVE_ARGON2LIB
|
||||
case PHP_PASSWORD_ARGON2I:
|
||||
{
|
||||
argon2_type type = Argon2_i;
|
||||
|
||||
status = argon2_verify(hash, password, password_len, type);
|
||||
|
||||
if (status == ARGON2_OK) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case PHP_PASSWORD_BCRYPT:
|
||||
case PHP_PASSWORD_UNKNOWN:
|
||||
default:
|
||||
{
|
||||
if ((ret = php_crypt(password, (int)password_len, hash, (int)hash_len, 1)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (ZSTR_LEN(ret) != hash_len || hash_len < 13) {
|
||||
zend_string_free(ret);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* We're using this method instead of == in order to provide
|
||||
* resistance towards timing attacks. This is a constant time
|
||||
* equality check that will always check every byte of both
|
||||
* values. */
|
||||
for (i = 0; i < hash_len; i++) {
|
||||
status |= (ZSTR_VAL(ret)[i] ^ hash[i]);
|
||||
}
|
||||
|
||||
zend_string_free(ret);
|
||||
|
||||
RETURN_BOOL(status == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ZSTR_LEN(ret) != hash_len || hash_len < 13) {
|
||||
zend_string_free(ret);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* We're using this method instead of == in order to provide
|
||||
* resistance towards timing attacks. This is a constant time
|
||||
* equality check that will always check every byte of both
|
||||
* values. */
|
||||
for (i = 0; i < hash_len; i++) {
|
||||
status |= (ZSTR_VAL(ret)[i] ^ hash[i]);
|
||||
}
|
||||
|
||||
zend_string_free(ret);
|
||||
|
||||
RETURN_BOOL(status == 0);
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string password_hash(string password, int algo, array options = array())
|
||||
/* {{{ proto string password_hash(string password, int algo[, array options = array()])
|
||||
Hash a password */
|
||||
PHP_FUNCTION(password_hash)
|
||||
{
|
||||
@ -267,7 +364,13 @@ PHP_FUNCTION(password_hash)
|
||||
size_t salt_len = 0, required_salt_len = 0, hash_format_len;
|
||||
HashTable *options = 0;
|
||||
zval *option_buffer;
|
||||
zend_string *result;
|
||||
|
||||
#if HAVE_ARGON2LIB
|
||||
size_t time_cost = PHP_PASSWORD_ARGON2_TIME_COST;
|
||||
size_t memory_cost = PHP_PASSWORD_ARGON2_MEMORY_COST;
|
||||
size_t threads = PHP_PASSWORD_ARGON2_THREADS;
|
||||
argon2_type type = Argon2_i;
|
||||
#endif
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|H", &password, &password_len, &algo, &options) == FAILURE) {
|
||||
return;
|
||||
@ -275,23 +378,57 @@ PHP_FUNCTION(password_hash)
|
||||
|
||||
switch (algo) {
|
||||
case PHP_PASSWORD_BCRYPT:
|
||||
{
|
||||
zend_long cost = PHP_PASSWORD_BCRYPT_COST;
|
||||
{
|
||||
zend_long cost = PHP_PASSWORD_BCRYPT_COST;
|
||||
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "cost", sizeof("cost")-1)) != NULL) {
|
||||
cost = zval_get_long(option_buffer);
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "cost", sizeof("cost")-1)) != NULL) {
|
||||
cost = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
if (cost < 4 || cost > 31) {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid bcrypt cost parameter specified: " ZEND_LONG_FMT, cost);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
required_salt_len = 22;
|
||||
sprintf(hash_format, "$2y$%02ld$", (long) cost);
|
||||
hash_format_len = 7;
|
||||
}
|
||||
break;
|
||||
#if HAVE_ARGON2LIB
|
||||
case PHP_PASSWORD_ARGON2I:
|
||||
{
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "memory_cost", sizeof("memory_cost")-1)) != NULL) {
|
||||
memory_cost = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
if (cost < 4 || cost > 31) {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid bcrypt cost parameter specified: " ZEND_LONG_FMT, cost);
|
||||
RETURN_NULL();
|
||||
if (memory_cost > ARGON2_MAX_MEMORY || memory_cost < ARGON2_MIN_MEMORY) {
|
||||
php_error_docref(NULL, E_WARNING, "Memory cost is outside of allowed memory range", memory_cost);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "time_cost", sizeof("time_cost")-1)) != NULL) {
|
||||
time_cost = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
if (time_cost > ARGON2_MAX_TIME || time_cost < ARGON2_MIN_TIME) {
|
||||
php_error_docref(NULL, E_WARNING, "Time cost is outside of allowed time range", time_cost);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if (options && (option_buffer = zend_hash_str_find(options, "threads", sizeof("threads")-1)) != NULL) {
|
||||
threads = zval_get_long(option_buffer);
|
||||
}
|
||||
|
||||
if (threads > ARGON2_MAX_LANES || threads == 0) {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid number of threads", threads);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
required_salt_len = 16;
|
||||
}
|
||||
|
||||
required_salt_len = 22;
|
||||
sprintf(hash_format, "$2y$%02ld$", (long) cost);
|
||||
hash_format_len = 7;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
#endif
|
||||
case PHP_PASSWORD_UNKNOWN:
|
||||
default:
|
||||
php_error_docref(NULL, E_WARNING, "Unknown password hashing algorithm: " ZEND_LONG_FMT, algo);
|
||||
@ -356,30 +493,86 @@ PHP_FUNCTION(password_hash)
|
||||
salt_len = required_salt_len;
|
||||
}
|
||||
|
||||
salt[salt_len] = 0;
|
||||
switch (algo) {
|
||||
case PHP_PASSWORD_BCRYPT:
|
||||
{
|
||||
zend_string *result;
|
||||
salt[salt_len] = 0;
|
||||
|
||||
hash = safe_emalloc(salt_len + hash_format_len, 1, 1);
|
||||
sprintf(hash, "%s%s", hash_format, salt);
|
||||
hash[hash_format_len + salt_len] = 0;
|
||||
hash = safe_emalloc(salt_len + hash_format_len, 1, 1);
|
||||
sprintf(hash, "%s%s", hash_format, salt);
|
||||
hash[hash_format_len + salt_len] = 0;
|
||||
|
||||
efree(salt);
|
||||
efree(salt);
|
||||
|
||||
/* This cast is safe, since both values are defined here in code and cannot overflow */
|
||||
hash_len = (int) (hash_format_len + salt_len);
|
||||
/* This cast is safe, since both values are defined here in code and cannot overflow */
|
||||
hash_len = (int) (hash_format_len + salt_len);
|
||||
|
||||
if ((result = php_crypt(password, (int)password_len, hash, hash_len, 1)) == NULL) {
|
||||
efree(hash);
|
||||
RETURN_FALSE;
|
||||
if ((result = php_crypt(password, (int)password_len, hash, hash_len, 1)) == NULL) {
|
||||
efree(hash);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
efree(hash);
|
||||
|
||||
if (ZSTR_LEN(result) < 13) {
|
||||
zend_string_free(result);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STR(result);
|
||||
}
|
||||
break;
|
||||
#if HAVE_ARGON2LIB
|
||||
case PHP_PASSWORD_ARGON2I:
|
||||
{
|
||||
size_t out_len = 32;
|
||||
size_t encoded_len;
|
||||
int status = 0;
|
||||
|
||||
encoded_len = argon2_encodedlen(
|
||||
time_cost,
|
||||
memory_cost,
|
||||
threads,
|
||||
(uint32_t)salt_len,
|
||||
out_len
|
||||
);
|
||||
|
||||
zend_string *out = zend_string_alloc(out_len, 0);
|
||||
zend_string *encoded = zend_string_alloc(encoded_len, 0);
|
||||
|
||||
status = argon2_hash(
|
||||
time_cost,
|
||||
memory_cost,
|
||||
threads,
|
||||
password,
|
||||
password_len,
|
||||
salt,
|
||||
salt_len,
|
||||
out->val,
|
||||
out_len,
|
||||
encoded->val,
|
||||
encoded_len,
|
||||
type,
|
||||
ARGON2_VERSION_NUMBER
|
||||
);
|
||||
|
||||
efree(out);
|
||||
efree(salt);
|
||||
|
||||
if (status != ARGON2_OK) {
|
||||
efree(encoded);
|
||||
php_error_docref(NULL, E_WARNING, argon2_error_message(status));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STR(encoded);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
efree(hash);
|
||||
|
||||
if (ZSTR_LEN(result) < 13) {
|
||||
zend_string_free(result);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STR(result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Anthony Ferrara <ircmaxell@php.net> |
|
||||
| Charles R. Portwood II <charlesportwoodii@erianna.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
@ -28,13 +29,21 @@ PHP_FUNCTION(password_get_info);
|
||||
|
||||
PHP_MINIT_FUNCTION(password);
|
||||
|
||||
#define PHP_PASSWORD_DEFAULT PHP_PASSWORD_BCRYPT
|
||||
|
||||
#define PHP_PASSWORD_DEFAULT PHP_PASSWORD_BCRYPT
|
||||
#define PHP_PASSWORD_BCRYPT_COST 10
|
||||
|
||||
#if HAVE_ARGON2LIB
|
||||
#define PHP_PASSWORD_ARGON2_MEMORY_COST 1<<10
|
||||
#define PHP_PASSWORD_ARGON2_TIME_COST 2
|
||||
#define PHP_PASSWORD_ARGON2_THREADS 2
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
PHP_PASSWORD_UNKNOWN,
|
||||
PHP_PASSWORD_BCRYPT
|
||||
PHP_PASSWORD_UNKNOWN,
|
||||
PHP_PASSWORD_BCRYPT,
|
||||
#if HAVE_ARGON2LIB
|
||||
PHP_PASSWORD_ARGON2I,
|
||||
#endif
|
||||
} php_password_algo;
|
||||
|
||||
#endif
|
||||
|
29
ext/standard/tests/password/password_get_info_argon2.phpt
Normal file
29
ext/standard/tests/password/password_get_info_argon2.phpt
Normal file
@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Test normal operation of password_get_info() with Argon2
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!defined('PASSWORD_ARGON2I')) die('Skipped: password_get_info not built with Argon2');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(password_get_info('$argon2i$v=19$m=65536,t=3,p=1$SWhIcG5MT21Pc01PbWdVZw$WagZELICsz7jlqOR2YzoEVTWb2oOX1tYdnhZYXxptbU'));
|
||||
echo "OK!";
|
||||
?>
|
||||
--EXPECT--
|
||||
array(3) {
|
||||
["algo"]=>
|
||||
int(2)
|
||||
["algoName"]=>
|
||||
string(7) "argon2i"
|
||||
["options"]=>
|
||||
array(3) {
|
||||
["memory_cost"]=>
|
||||
int(65536)
|
||||
["time_cost"]=>
|
||||
int(3)
|
||||
["threads"]=>
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
OK!
|
18
ext/standard/tests/password/password_hash_argon2.phpt
Normal file
18
ext/standard/tests/password/password_hash_argon2.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Test normal operation of password_hash() with argon2
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!defined('PASSWORD_ARGON2I')) die('Skipped: password_hash not built with Argon2');
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$password = "the password for testing 12345!";
|
||||
|
||||
$hash = password_hash($password, PASSWORD_ARGON2I);
|
||||
var_dump(password_verify($password, $hash));
|
||||
|
||||
echo "OK!";
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
OK!
|
21
ext/standard/tests/password/password_hash_error_argon2.phpt
Normal file
21
ext/standard/tests/password/password_hash_error_argon2.phpt
Normal file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Test error operation of password_hash() with argon2
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!defined('PASSWORD_ARGON2I')) die('Skipped: password_hash not built with Argon2');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(password_hash('test', PASSWORD_ARGON2I, ['memory_cost' => 0]));
|
||||
var_dump(password_hash('test', PASSWORD_ARGON2I, ['time_cost' => 0]));
|
||||
var_dump(password_hash('test', PASSWORD_ARGON2I, ['threads' => 0]));
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: password_hash(): Memory cost is outside of allowed memory range in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: password_hash(): Time cost is outside of allowed time range in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: password_hash(): Invalid number of threads in %s on line %d
|
||||
NULL
|
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Test normal operation of password_needs_rehash() with argon2
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!defined('PASSWORD_ARGON2I')) die('Skipped: password_needs_rehash not built with Argon2');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$hash = '$argon2i$v=19$m=65536,t=3,p=1$YkprUktYN0lHQTd2bWRFeA$79aA+6IvgclpDAJVoezProlqzIPy7do/P0sBDXS9Nn0';
|
||||
var_dump(password_needs_rehash($hash, PASSWORD_ARGON2I));
|
||||
var_dump(password_needs_rehash($hash, PASSWORD_ARGON2I, ['memory_cost' => 1<<17]));
|
||||
var_dump(password_needs_rehash($hash, PASSWORD_ARGON2I, ['time_cost' => 2]));
|
||||
var_dump(password_needs_rehash($hash, PASSWORD_ARGON2I, ['threads' => 2]));
|
||||
echo "OK!";
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
OK!
|
18
ext/standard/tests/password/password_verify_argon2.phpt
Normal file
18
ext/standard/tests/password/password_verify_argon2.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Test normal operation of password_verify() with argon2
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!defined('PASSWORD_ARGON2I')) die('Skipped: password_verify not built with Argon2');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(password_verify('test', '$argon2i$v=19$m=65536,t=3,p=1$OEVjWWs2Z3YvWlNZQ0ZmNw$JKin7ahjmh8JYvMyFcXri0Ss/Uvd3uYpD7MG6C/5Cy0'));
|
||||
|
||||
var_dump(password_verify('argon2', '$argon2i$v=19$m=65536,t=3,p=1$OEVjWWs2Z3YvWlNZQ0ZmNw$JKin7ahjmh8JYvMyFcXri0Ss/Uvd3uYpD7MG6C/5Cy0'));
|
||||
echo "OK!";
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(false)
|
||||
OK!
|
Loading…
Reference in New Issue
Block a user