wiki:PasswordHash

Overview

Currently BOINC stores passwords in the database using following hash:

md5_string(passwd+email_addr)

This is no longer considered to be secure for storage of passwords. Brute force attacks on md5 hashed passwords are possible due to the speed that md5 hashes can be computed. As a result, in the event that the database of a BOINC project were compromised, the passwords would be at risk of being cracked.

New Hashing Function

For PHP code, will will use password_hash (https://php.net/manual/en/function.password-hash.php). We will also use a compatibility library for this to support older versions of PHP (https://github.com/ircmaxell/password_compat). As an example of how to use password_hash:

<?php
    require('lib/password.php');  //password_hash compatability library
    $passwd = "test";
    $passwd_hash = password_hash ( $passwd , PASSWORD_DEFAULT );
    echo $passwd_hash . PHP_EOL;
    if ( password_verify($passwd, $passwd_hash) ) {
        echo "Password valid" . PHP_EOL;
    } else {
        echo "Invalid password" . PHP_EOL;
    }
?>

At the moment, the new hashing will not need to be done in C code. However, if this changes, the implementation found here: http://www.openwall.com/crypt/ can be used.

Approach

The purpose of this change is to make the storage of the password secure. Due to the usage of the existing md5 password hash in the client, web_rpc's and website, it would be difficult to eliminate usage of the md5 version of the hash at this time. As a result, this change focuses simply on storing the password in a secure way.

The password will be stored in the existing field in the database as follows:

$database_password_hash = password_hash ( md5_string(passwd+email_addr) , PASSWORD_DEFAULT );

Migration

Because password_hash is designed to be computational expensive, performing an update on all passwords on the system immediately could potentially be a long running action – especially on some of the larger BOINC projects. As a result, the system will store the password in the new format when created or updated and will “rehash” the password whenever the password is verified.

Verify Password

Verifying the password will look like the following:

$password_hash = md5_string(passwd+email_addr);  //or passed in via web rpc
$database_password_hash = fetch from database for user
if ( $password_hash ==$database_password_hash|| password_verify($password_hash,$database_password_hash) ) {
    //this is a valid password
} else {
    //this is not a valid password
}

Rehash Password

Every time that a password is verified, it will then be checked to see if it needs to be rehashed. This will look like the following:

$password_hash = md5_string(passwd+email_addr);  //or passed in via web rpc
$database_password_hash = fetch from database
if ( $password_hash ==$database_password_hash|| password_needs_rehash($password_hash,$database_password_hash) ) {
    $new_database_password_hash= password_hash ( $password_hash , PASSWORD_DEFAULT );
    //save $new_database_password_hash to database
}

This will convert the password hashes over time to the stronger hashed formula. A script will be developed that can be used at a later time (or gradually over time) to update those password hashes that have not yet been converted. Password hashes in the new format will start with $2$10 and are therefore easily identifiable from the md5 hashed passwords.

Changes

The client will not require any changes nor will external systems that use the Web RPCs.

The website will need to be changed in order to add the new logic to validate and rehash a password and to use the new hash algorithm when stored in the database.

Last modified 6 months ago Last modified on 02/16/18 14:56:41