“Since 2017, NIST recommends using a secret input when hashing memorized secrets such as passwords. By mixing in a secret input (commonly called a "pepper"), one prevents an attacker from brute-forcing the password hashes altogether, even if they have the hash and salt. For example, an SQL injection typically affects only the database, not files on disk, so a pepper stored in a config file would still be out of reach for the attacker. A pepper must be randomly generated once and can be the same for all users. Many password leaks could have been made completely useless if site owners had done this.
Since there is no pepper parameter for password_hash (even though Argon2 has a "secret" parameter, PHP does not allow to set it), the correct way to mix in a pepper is to use hash_hmac().” php.net
Solital uses the SecurePassword package to validate passwords and prevent attacks. That is, even if someone manages to access the hash created with this package, using only the native password_verify
function WILL NOT return true
.
Solital has two password helpers:
pass_hash($password, int $cost = 10)
pass_verify($password, string $hash)
Unlike just using password_hash
function, these helpers adds a secret entry (commonly called a pepper) to make it difficult to break the generated hash.
To change the type of algorithm used in encryption, the cost, among other options, you can edit the auth.yaml
file.
password:
algorithm: default # default - argon2 - argon2d
pepper: b3f952d5d9adea6f63bee9d4c6fceeaa
cost: 10
memory_cost: ''
time_cost: ''
threads: ''
crypt_type: openssl
wait_microseconds: 25000
In the algorithm
key, you can add the following values: default
, argon2
and argon2d
. For more information about other PHP constants, see this link.
As mentioned in the introduction, the SecurePassword
package uses a “pepper” value. To change the value of this pepper, you can edit the value of the peeper
key in the auth.yaml
file. However, it is recommended to use the APP_HASH
variable. If this variable does not exist in your project, run the command php vinci generate:hash
.
If this variable is present in the .env
file, then you can delete the peeper
in the auth.yaml
file.
By default, peeper is encrypted using OpenSSL. You can switch to Sodium encryption by changing the value of the crypt_type
variable in the auth.yaml
file.
crypt_type: sodium
You can set some requirements when creating a password, such as password length, special characters, etc.
use Solital\Core\Auth\Password;
$password = new Password();
$password->setMinimumLength(15);
$password->requireUppercase();
$password->requireDigits();
$password->requireSpecialChars();
$password->setSpecialChars('!@#%');
$result = $password->validatePassword('strongpassword');
if ($result === true) {
echo "Password meets the policy requirements.";
// Go and do things with it
} else {
echo "Password validation failed. Errors:\n";
print_r($result);
// Go and display these error messages to your user
}
To customize error messages, you should use the setCustomErrorMessages
method. Using the example from the previous topic, the code would look like this:
use Solital\Core\Auth\Password;
$customErrorMessages = [
'min_length' => 'Your password is too short. It must be at least 15 characters long.',
'uppercase' => 'Your password must contain at least one uppercase letter.',
];
$password = new Password();
$password->setMinimumLength(15);
$password->requireUppercase();
$password->requireDigits();
$password->requireSpecialChars();
$password->setSpecialChars('!@#%');
$password->setCustomErrorMessages($customErrorMessages);
$result = $password->validatePassword('strongpassword');
if ($result === true) {
echo "Password meets the policy requirements.";
// Go and do things with it
} else {
echo "Password validation failed. Errors:\n";
print_r($result);
// Go and display these error messages to your user
}