Subversion Repositories oidplus

Compare Revisions

Regard whitespace Rev 1095 → Rev 1096

/trunk/vendor/danielmarschall/php_utils/misc_functions.inc.php
2,8 → 2,8
 
/*
* PHP Utilities - Misc functions
* Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft
* Revision: 2022-12-27
* Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
* Revision: 2023-02-27
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
141,3 → 141,68
$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
return ((strpos($ua,'MSIE ') !== false) || (strpos($ua,'Trident/') !== false));
}
 
if (!function_exists('str_ends_with')) {
// PHP 7.x compatibility
function str_ends_with($haystack, $needle) {
$length = strlen($needle);
return $length > 0 ? substr($haystack, -$length) === $needle : true;
}
}
 
if (!function_exists('str_starts_with')) {
// PHP 7.x compatibility
function str_starts_with($haystack, $needle) {
return strpos($haystack, $needle) === 0;
}
}
 
function random_bytes_ex($len) {
if ($len === 0) return '';
assert($len > 0);
 
if (function_exists('random_bytes')) {
try {
$a = random_bytes($len);
} catch (Exception $e) { $a = null; }
if ($a) return $a;
}
 
if (function_exists('openssl_random_pseudo_bytes')) {
try {
$a = openssl_random_pseudo_bytes($len);
} catch (Exception $e) { $a = null; }
if ($a) return $a;
}
 
if (function_exists('mcrypt_create_iv')) {
if (defined('MCRYPT_DEV_URANDOM')) {
try {
$a = bin2hex(mcrypt_create_iv($len, MCRYPT_DEV_URANDOM));
} catch (Exception $e) { $a = null; }
if ($a) return $a;
}
 
if (defined('MCRYPT_DEV_RANDOM')) {
try {
$a = bin2hex(mcrypt_create_iv($len, MCRYPT_DEV_RANDOM));
} catch (Exception $e) { $a = null; }
if ($a) return $a;
}
 
if (defined('MCRYPT_RAND')) {
try {
$a = bin2hex(mcrypt_create_iv($len, MCRYPT_RAND));
} catch (Exception $e) { $a = null; }
if ($a) return $a;
}
}
 
// Fallback to non-secure RNG
$a = '';
while (strlen($a) < $len*2) {
$a .= sha1(uniqid((string)mt_rand(), true));
}
$a = substr($a, 0, $len*2);
return hex2bin($a);
}
/trunk/vendor/danielmarschall/php_utils/password_hash_ex.inc.php
2,8 → 2,8
 
/*
* password_hash_ex() function which integrates crypt() algorithms in password_hash().
* Revision 2023-02-26
* Copyright 2023 Daniel Marschall, ViaThinkSoft
* Revision 2023-02-27
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
25,11 → 25,15
define('PASSWORD_SHA256', 'sha256');
define('PASSWORD_SHA512', 'sha512');
 
require_once __DIR__ . '/misc_functions.inc.php';
 
function des_compat_salt($salt_len) {
if ($salt_len <= 0) return '';
$characters = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$salt = '';
$bytes = random_bytes_ex($salt_len);
for ($i=0; $i<$salt_len; $i++) {
$salt .= $characters[rand(0, strlen($characters)-1)]; // TODO: use rand() to make the RND cryptographical secure
$salt .= $characters[ord($bytes[$i]) % strlen($characters)];
}
return $salt;
}
57,37 → 61,38
* @return string Crypt compatible password hash
*/
function password_hash_ex($password, $algo, $options=array()) {
$salt = null;
if (($algo === PASSWORD_STD_DES) && defined('CRYPT_STD_DES')) {
// Standard DES-based hash with a two character salt from the alphabet "./0-9A-Za-z". Using invalid characters in the salt will cause crypt() to fail.
$salt = des_compat_salt(2);
return crypt($password, $salt);
} else if (($algo === PASSWORD_EXT_DES) && defined('CRYPT_EXT_DES')) {
// Extended DES-based hash. The "salt" is a 9-character string consisting of an underscore followed by 4 characters of iteration count and 4 characters of salt. Each of these 4-character strings encode 24 bits, least significant character first. The values 0 to 63 are encoded as ./0-9A-Za-z. Using invalid characters in the salt will cause crypt() to fail.
$iterations = isset($options['iterations']) ? $options['iterations'] : 725;
$salt = '_' . base64_int_encode($iterations) . des_compat_salt(4);
return crypt($password, $salt);
} else if (($algo === PASSWORD_MD5) && defined('CRYPT_MD5')) {
// MD5 hashing with a twelve character salt starting with $1$
$salt = '$1$'.des_compat_salt(12).'$';
return crypt($password, $salt);
} else if (($algo === PASSWORD_BLOWFISH) && defined('CRYPT_BLOWFISH')) {
// Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithm and must be in range 04-31, values outside this range will cause crypt() to fail. "$2x$" hashes are potentially weak; "$2a$" hashes are compatible and mitigate this weakness. For new hashes, "$2y$" should be used.
$algo = '$2y$'; // most secure
$cost = isset($options['cost']) ? $options['cost'] : 10;
$salt = $algo.str_pad($cost,2,'0',STR_PAD_LEFT).'$'.des_compat_salt(22).'$';
return crypt($password, $salt);
} else if (($algo === PASSWORD_SHA256) && defined('CRYPT_SHA256')) {
// SHA-256 hash with a sixteen character salt prefixed with $5$. If the salt string starts with 'rounds=<N>$', the numeric value of N is used to indicate how many times the hashing loop should be executed, much like the cost parameter on Blowfish. The default number of rounds is 5000, there is a minimum of 1000 and a maximum of 999,999,999. Any selection of N outside this range will be truncated to the nearest limit.
$algo = '$5$';
$rounds = isset($options['rounds']) ? $options['rounds'] : 5000;
$salt = $algo.'rounds='.$rounds.'$'.des_compat_salt(16).'$';
return crypt($password, $salt);
} else if (($algo === PASSWORD_SHA512) && defined('CRYPT_SHA512')) {
// SHA-512 hash with a sixteen character salt prefixed with $6$. If the salt string starts with 'rounds=<N>$', the numeric value of N is used to indicate how many times the hashing loop should be executed, much like the cost parameter on Blowfish. The default number of rounds is 5000, there is a minimum of 1000 and a maximum of 999,999,999. Any selection of N outside this range will be truncated to the nearest limit.
$algo = '$6$';
$rounds = isset($options['rounds']) ? $options['rounds'] : 5000;
$salt = $algo.'rounds='.$rounds.'$'.des_compat_salt(16).'$';
return crypt($password, $salt);
}
 
if (!is_null($salt)) {
$out = crypt($password, $salt);
if (strlen($out) < 13) throw new Exception("crypt() failed");
return $out;
} else {
// $algo === PASSWORD_DEFAULT
// $algo === PASSWORD_BCRYPT
/trunk/vendor/danielmarschall/php_utils/vts_crypt.inc.php
2,8 → 2,8
 
/*
* ViaThinkSoft Modular Crypt Format 1.0
* Copyright 2023 Daniel Marschall, ViaThinkSoft
* Revision 2023-02-26
* Copyright 2023 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.