url_scanner_ex.c ftp_fopen_wrapper.c http_fopen_wrapper.c \
php_fopen_wrapper.c credits.c css.c var_unserializer.c ftok.c sha1.c \
user_filters.c uuencode.c filters.c proc_open.c password.c \
- streamsfuncs.c http.c flock_compat.c random.c", false /* never shared */,
+ streamsfuncs.c http.c flock_compat.c random.c \
+ argon2lib/argon2.c argon2lib/core.c argon2lib/blake2/blake2b.c \
+ argon2lib/thread.c argon2lib/encoding.c argon2lib/ref.c", false /* never shared */,
'/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
PHP_INSTALL_HEADERS("", "ext/standard");
if (PHP_MBREGEX != "no") {
CHECK_HEADER_ADD_INCLUDE("oniguruma.h", "CFLAGS_STANDARD", PHP_MBREGEX + ";ext\\mbstring\\oniguruma")
}
PHP_INSTALL_HEADERS("", "ext/standard");
+PHP_INSTALL_HEADERS([ext/standard/argon2lib])
static php_password_algo php_password_determine_algo(const char *hash, const size_t len)
{
- if (hash[0] == '$' && strstr(hash, "argon2i")) {
+ if (len > 3 && hash[0] == '$' && hash[1] == '2' && hash[2] == 'y' && len == 60) {
+ return PHP_PASSWORD_BCRYPT;
+ } else if (hash[0] == '$' && strstr(hash, "argon2i")) {
return PHP_PASSWORD_ARGON2I;
} else if (hash[0] == '$' && strstr(hash, "argon2d")) {
return PHP_PASSWORD_ARGON2D;
- } else if (len > 3 && hash[0] == '$' && hash[1] == '2' && hash[2] == 'y' && len == 60) {
- return PHP_PASSWORD_BCRYPT;
}
return PHP_PASSWORD_UNKNOWN;
algo = php_password_determine_algo(hash, (size_t) hash_len);
switch(algo) {
+ case PHP_PASSWORD_ARGON2I:
+ case PHP_PASSWORD_ARGON2D:
+ {
+ argon2_type type = Argon2_i;
+
+ if (strstr(hash, "argon2d")) {
+ type = Argon2_d;
+ } else if (strstr(hash, "argon2i")) {
+ type = Argon2_i;
+ }
+
+ status = argon2_verify(hash, password, password_len, type);
+
+ if (status == ARGON2_OK) {
+ RETURN_TRUE;
+ }
+
+ RETURN_FALSE;
+ }
+ break;
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;
RETURN_BOOL(status == 0);
}
- case PHP_PASSWORD_ARGON2I:
- case PHP_PASSWORD_ARGON2D:
- {
- argon2_type type = Argon2_i;
-
- if (strstr(hash, "argon2d")) {
- type = Argon2_d;
- } else if (strstr(hash, "argon2i")) {
- type = Argon2_i;
- }
-
- status = argon2_verify(hash, password, password_len, type);
-
- if (status == ARGON2_OK) {
- RETURN_TRUE;
- }
-
- RETURN_FALSE;
- }
- case PHP_PASSWORD_UNKNOWN:
- default:
- RETURN_FALSE;
}
RETURN_FALSE;
size_t salt_len = 0, required_salt_len = 0, hash_format_len;
HashTable *options = 0;
zval *option_buffer;
- zend_string *result;
// Argon2 Options
size_t t_cost = PHP_PASSWORD_ARGON2_TIME_COST;
}
if (threads > ARGON2_MAX_LANES || threads == 0) {
- php_error_docref(NULL, E_WARNING, "Invalid numeric input for threads", threads);
+ php_error_docref(NULL, E_WARNING, "Invalid number of threads", threads);
RETURN_NULL();
}
switch (algo) {
case PHP_PASSWORD_BCRYPT:
{
+ zend_string *result;
salt[salt_len] = 0;
hash = safe_emalloc(salt_len + hash_format_len, 1, 1);
size_t out_len = 32;
size_t encoded_len;
- int result = 0;
+ int status = 0;
encoded_len = argon2_encodedlen(
t_cost,
encoded = emalloc(encoded_len + 1);
out = emalloc(out_len + 1);
- result = argon2_hash(
+ status = argon2_hash(
t_cost,
m_cost,
threads,
efree(salt);
efree(encoded);
- if (result != ARGON2_OK) {
- php_error_docref(NULL, E_WARNING, argon2_error_message(result));
+ if (status != ARGON2_OK) {
+ php_error_docref(NULL, E_WARNING, argon2_error_message(status));
RETURN_FALSE;
}
typedef enum {
PHP_PASSWORD_UNKNOWN,
PHP_PASSWORD_BCRYPT,
- PHP_PASSWORD_ARGON2I,
- PHP_PASSWORD_ARGON2D
+ PHP_PASSWORD_ARGON2D,
+ PHP_PASSWORD_ARGON2I
} php_password_algo;
#endif
var_dump(password_get_info('$2y$11$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100'));
// Test Non-Bcrypt
var_dump(password_get_info('$1$rasmusle$rISCgZzpwk3UhDidwXvin0'));
-// Test Argon2
-//var_dump(password_get_info('$argon2i$v=19$m=65536,t=3,p=1$SWhIcG5MT21Pc01PbWdVZw$WagZELICsz7jlqOR2YzoEVTWb2oOX1tYdnhZYXxptbU'));
-
+// Test Argon2i
+var_dump(password_get_info('$argon2i$v=19$m=65536,t=3,p=1$SWhIcG5MT21Pc01PbWdVZw$WagZELICsz7jlqOR2YzoEVTWb2oOX1tYdnhZYXxptbU'));
+// Test Argon2d
+var_dump(password_get_info('$argon2d$v=19$m=32768,t=2,p=1$YWpxd0VYRW9MLmp6VjFPZw$pWV5IsbBfjEK5c0bHzvAo0FsDNHUyM4p6j8vf2cxzb8'));
echo "OK!";
?>
--EXPECT--
}
array(3) {
["algo"]=>
- int(2)
+ int(3)
["algoName"]=>
string(7) "argon2i"
["options"]=>
int(1)
}
}
+array(3) {
+ ["algo"]=>
+ int(2)
+ ["algoName"]=>
+ string(7) "argon2d"
+ ["options"]=>
+ array(3) {
+ ["m_cost"]=>
+ int(32768)
+ ["t_cost"]=>
+ int(2)
+ ["threads"]=>
+ int(1)
+ }
+}
OK!
var_dump($hash === crypt("foo", $hash));
+$hash = password_hash('foo', PASSWORD_ARGON2);
+var_dump(strlen($hash));
+var_dump(password_verify('foo', $hash));
+
+$hash = password_hash('foo', PASSWORD_ARGON2I);
+var_dump(strlen($hash));
+var_dump(password_verify('foo', $hash));
+
+$hash = password_hash('foo', PASSWORD_ARGON2D);
+var_dump(strlen($hash));
+var_dump(password_verify('foo', $hash));
+
echo "OK!";
?>
--EXPECT--
int(60)
bool(true)
-OK!
\ No newline at end of file
+int(99)
+bool(true)
+int(99)
+bool(true)
+int(99)
+bool(true)
+OK!
/* Non-string salt, checking for memory leaks */
var_dump(password_hash('123', PASSWORD_BCRYPT, array('salt' => 1234)));
+var_dump(password_hash('test', PASSWORD_ARGON2, ['m_cost' => 0]));
+
+var_dump(password_hash('test', PASSWORD_ARGON2, ['t_cost' => 0]));
+
+var_dump(password_hash('test', PASSWORD_ARGON2, ['threads' => 0]));
+
?>
--EXPECTF--
Warning: password_hash() expects at least 2 parameters, 0 given in %s on line %d
Warning: password_hash(): Provided salt is too short: 4 expecting 22 in %s on line %d
NULL
+
+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
+
// Should Issue Needs Rehash, Since Foo is cast to 0...
var_dump(password_needs_rehash('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', PASSWORD_BCRYPT, array('cost' => 'foo')));
-
-
+var_dump(password_needs_rehash('$argon2i$v=19$m=65536,t=3,p=1$YkprUktYN0lHQTd2bWRFeA$79aA+6IvgclpDAJVoezProlqzIPy7do/P0sBDXS9Nn0', PASSWORD_ARGON2, ['m_cost' => 1<<17]));
+var_dump(password_needs_rehash('$argon2i$v=19$m=65536,t=3,p=1$YkprUktYN0lHQTd2bWRFeA$79aA+6IvgclpDAJVoezProlqzIPy7do/P0sBDXS9Nn0', PASSWORD_ARGON2, ['t_cost' => 2]));
+var_dump(password_needs_rehash('$argon2i$v=19$m=65536,t=3,p=1$YkprUktYN0lHQTd2bWRFeA$79aA+6IvgclpDAJVoezProlqzIPy7do/P0sBDXS9Nn0', PASSWORD_ARGON2, ['threads' => 2]));
echo "OK!";
?>
--EXPECT--
bool(true)
bool(false)
bool(true)
+bool(true)
+bool(true)
+bool(true)
OK!
var_dump(password_verify("foo", "$1"));
+var_dump(password_verify('test', '$argon2d$v=19$m=32768,t=2,p=1$YWpxd0VYRW9MLmp6VjFPZw$pWV5IsbBfjEK5c0bHzvAo0FsDNHUyM4p6j8vf2cxzb8'));
+
+var_dump(password_verify('argon2', '$argon2d$v=19$m=32768,t=2,p=1$YWpxd0VYRW9MLmp6VjFPZw$pWV5IsbBfjEK5c0bHzvAo0FsDNHUyM4p6j8vf2cxzb8'));
+
+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(false)
bool(true)
bool(false)
-OK!
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+OK!
\ No newline at end of file