Protection against identity theft through the extension of PHP with Argon2d

By extending PHP with Argon2d, users and service providers can now be even better protected actively and preventively against identity theft on the Internet. Read more about the implementation and the dangers of identity theft in this blog article and find out how you can protect yourself and your users against it.

Reading time:
12 min
Protection against identity theft through the extension of PHP with Argon2d

Looking at the digital landscape, it is clear that identity theft is no longer an abstract threat. According to a study from 2016, 33% of Germans surveyed have been the victim of identity theft at least once. The consequences can be significant for both users and service providers. Among other things, users can suffer financial or emotional damage as a result of identity theft, while service providers can expect financial, legal and reputational consequences. For example, in the study mentioned above, 29% of affected users suffered financial loss with an average loss amount of €1,366.

In view of the fact that many users reuse their credentials for different services by using the same email address and password, data leaks pose a serious risk. They enable criminals to commit identity theft and therefore pose a threat to the security of users and service providers.

Prevention of identity theft

Many identity thefts can be prevented in advance by taking measures to prevent data leaks. However, data leaks cannot be completely ruled out due to software vulnerabilities, misconfigurations or human error. This fact is confirmed by regular media reports on new data leaks. In total, several billion user credentials can already be found on the Internet today.

In order to prevent identity theft as a result of data leaks, service providers must store user passwords in a secure form so that they can no longer be determined efficiently. For this purpose, user passwords are stored in a secure form using password hashing. The state of the art in password hashing is the use of the memory-hard hash function Argon2 to make attacks by specialized hardware more difficult. Of the three variants of Argon2, Argon2d offers the best protection against these attacks as long as there is no threat from side-channel attacks. If these cannot be ruled out, the Argon2id variant should be used for password hashing.

However, as it cannot be assumed that every service provider stores the credentials securely, the BSI and NIST require that the credentials are actively checked for compromise through data leaks as a further protective measure. The Identeco Credential Check can be used for this purpose, for example. It uses Argon2d to prevent attackers from misusing the Credential Check as an oracle to obtain credentials from data leaks collected by Identeco. In this case, Argon2d is not used for password hashing, so that the Credential Check can also be performed in environments that are vulnerable to side-channel attacks.

Password hashing

Password hashing is a method of securely storing passwords. One-way functions are used for this purpose. These are not reversible. An example of such one-way functions are cryptographic hash functions such as SHA2. With password hashing, the password itself is not stored directly. Instead, only the unique result of the one-way function is saved. This is also known as the password hash.

Memory-hard hash function

Memory-hard hash functions belong to the cryptographic hash functions. However, they require a lot of memory to calculate the hash. This property ensures that attackers cannot use specialized hardware such as GPUs, FPGAs and ASICs to try out a large number of password candidates in parallel. For this reason, memory-hard hash functions are ideal for password hashing.

General information about PHP

PHP is an open source scripting language that is ideal for developing websites. Over 75% of all websites use PHP as a server-side programming language. The Content Management System (CMS) WordPress, which is used by over 40% of all websites on the Internet, contributes significantly to this widespread use. In addition, many store systems such as Shopware or Magento are based on PHP, which together account for a market share of over 50% of store systems in Germany.

Plugins can be developed for numerous CMS and store systems that are based on PHP. These plugins could, for example, use the Identeco Credential Check to check the user credentials for compromise through data leaks in real time each time they log in. By installing this plugin, service providers could easily actively protect themselves and their users against identity theft as a result of data leaks.

Problems in the use of Argon2d in PHP

Although PHP is used by most websites as a programming language, it offers no direct support for Argon2d, neither for password hashing nor for implementing the Credential Check for CMS and store system plugins, for example. Since PHP 7.2, the Argon2i and Argon2id variants have been supported by PHP for password hashing. There are currently only two approaches for calculating Argon2d hashes in PHP.

The first approach uses the command line program argon2 to calculate Argon2d hashes, which can be accessed in PHP via the system()-method. An example function for calculating an Argon2d hash using this approach is shown below:

public function argon2d_hash(String $input_data, String $salt):String
{
    return system("echo -n " . $input_data . " | argon2 " . $salt . " -d -r");
}

Although this function calculates correct Argon2d hashes, it should not be used as it is vulnerable to “Command Injection” attacks (CWE-77). This is because special characters in the transferred input are not escaped. If this function is used for password hashing or the Credential Check, this can lead to serious security incidents. An attacker could execute any command on the server by choosing a suitable password or user name via the publicly accessible login page.

In addition, this approach cannot always be used for CMS and store system plugins for the Credential Check in shared hosting. This is because customers cannot make system-wide changes in shared hosting. Therefore, if the command line program argon2 is not pre-installed or the system()-method is blocked in the PHP installation, no plugin for the Credential Check can be used to actively prevent identity theft in this case.

Furthermore, there is a PHP Argon2 extension on GitHub that allows the use of Argon2d for password hashing. With this approach, however, the salt cannot be freely selected. As a result, this extension is not suitable for implementing the Credential Check, as this calculates the Argon2d hash of the user name with a static salt. Furthermore, this extension can only be used to a limited extent, as it does not support the current PHP versions 8.X.

For this reason, the PHPArgon2d extension and the PlainPHPArgon2d library were developed. These enable user-friendly use of Argon2d in PHP for both password hashing and the Credential Check.

Technical implementation

In the following, the technical implementation of the PHPArgon2d extension and the PlainPHPArgon2d library is described. Special features and problems encountered are discussed in particular.

Implementation of the PHPArgon2d extension

The PHPArgon2d extension provides user-friendly methods for creating, checking and recognizing required updates of Argon2d password hashes. To use the extension correctly, only the password or password hash needs to be passed. Other parameters are optional and are secure by default. To illustrate the user-friendly use of the extension, two example functions are presented below with which the extension can be used to authenticate users:

public function register_user(String $password, String $username):String
{
    try{
        // Calculate the password hash for the given password with the default cost parameters 
        $password_hash = argon2d_password_hash($password);
    }
    catch(Exceprion $e){
        // An error occurred while calculating the hash, which must now be handled
    }

    // Stores the password hash in the database
    $db.store($password_hash, $username)
}
public function check_credentials(String $password, String $username):bool
{
    // Get the user's stored password hash from the database
    $password_hash = db.getPasswordHash($username);

    try{
        // Check if the passed password matches the given password hash
        if(argon2d_password_hash_verify($password_hash, $password)){

            // Check if the stored password hash needs to be updated due to updated cost parameters 
            if(argon2d_password_hash_need_rehash($password_hash)){

                // Calculates a new password hash with the updated cost parameters 
                $new_password_hash = argon2d_password_hash($password);

                // Stores the new password hash in the database
                $db.store($new_password_hash, $username)
            }

            // Credentials correct 
            return true;
        }
        
        // Credentials incorrect
        return false;

    }
    catch(Exception $e){
        // An error has occurred during the verification or calculation of the hash, which must now be handled
    }
}

Furthermore, the extension can also be used to realise the Credential Check and thus actively protect against identity theft. The Argon2d hashes are calculated using libargon2, which is the official C reference implementation. However, the extension cannot be used in shared hosting, as no Argon2d password hashes should be calculated there due to the vulnerability to side-channel attacks.

Implementation of the PlainPHPArgon2d library

The PlainPHPArgon2d library was developed to enable the calculation of Argon2d hashes for the Credential Check in all types of web hosting and especially for plugins used in shared hosting. This implements the calculation of an Argon2d hash in accordance with the Argon2-RFC 9106 directly in PHP without external software dependencies and can therefore be used on all standard PHP installations for active protection against identity theft. Below is an example function that can be used to calculate an Argon2d hash for the Credential Check:

// Include the class for the Argon2d calculation
include_once("path/to/PlainArgon2d.php");

// Disables warning due to low cost parameters when calculating an Argon2d hash
error_reporting(E_ALL & ~E_USER_NOTICE);

public function get_argon2d_hash_username(String $username):String
{
    // Initialise Argon2d object 
    $argon2d = new PlainArgon2d();
    
    // Calculate the Argon2d hash of the username with a static salt and given cost parameters 
    return $argon2d->argon2d_raw_hash($username, "StaticSalt", 512, 1, 1, 16);
}

During the implementation of the library, however, some challenges arose. Firstly, PHP does not support unsigned 64-bit integers, so these have to be emulated, which leads to increased calculation times and memory consumption.

Secondly, PHP does not allow direct access to the memory, which means that the allocated memory cannot be safely deleted after the calculation. This makes the library vulnerabel to garbage collector attacks, which pose a risk in shared hosting. This problem can only be solved by not using the library in shared hosting. However, the benefits of the library for actively preventing identity theft through the Credential Check outweigh this risk.

Evaluation

For the practical use of Argon2d in PHP, the PHPArgon2d extension and the PlainPHPArgon2d library must be able to calculate Argon2d hashes efficiently. In order to evaluate this, the calculation times and memory consumption are analyzed on the VPS Hosting Linux S from IONOS as a function of memory requirements. The evaluation was carried out on an Ubuntu 22.04 with 2 GB RAM, 2 CPU cores and PHP version 8.1. Each measurement was repeated 100 times and the average value was used.

Evaluation of the PHPArgon2d extension

The following figure shows the measured results for the PHPArgon2d extension. This shows that the extension calculates Argon2d hashes efficiently and that it can be used in all applications in which the reference implementation is used to calculate Argon2d hashes.

Calculation times and memory consumption of the PHPArgon2d extension. The calculation times are on average 13.6% faster than those of the reference implementation. The average memory consumption is 1.2% higher than the specified memory requirement (the optimum).
Figure: Calculation times and memory consumption of the PHPArgon2d extension. The calculation times are on average 13.6% faster than those of the reference implementation. The average memory consumption is 1.2% higher than the specified memory requirement (the optimum).

Evaluation of the PlainPHPArgon2d library

The measured results for the PlainPHPArgon2d library are shown in the following figure. This shows that the direct implementation of Argon2d in PHP is not able to calculate Argon2d hashes efficiently due to the long calculation times and high memory consumption.

BCalculation times and memory consumption of the PlainPHPArgon2d library. The calculation times are on average 954 times slower than those of the reference implementation. The memory consumption is on average 22 times higher than the memory requirement passed (the optimum).
Figure: Calculation times and memory consumption of the PlainPHPArgon2d library. The calculation times are on average 954 times slower than those of the reference implementation. The memory consumption is on average 22 times higher than the memory requirement passed (the optimum).

The calculation of an Argon2d hash with a memory requirement of more than 7-MiB already exceeds the memory limit of 128-MiB of a standard PHP installation. As the library is therefore unable to calculate secure Argon2d password hashes on a standard PHP installation, it is not suitable for password hashing.

However, this is not a limitation, as the PlainPHPArgon2d library was not developed for password hashing. It was already clear during the design phase that a direct implementation of Argon2d in PHP cannot efficiently calculate Argon2d hashes due to the limitations of PHP. The main function of this library is therefore to enable the calculation of Argon2d hashes for the Credential Check on all types of web hosting.

The Credential Check calculates an Argon2d hash of the user name with a memory requirement of 0.5 MiB. With the library, this requires 12.6 MiB of memory. Due to the low cost parameters of the Credential Check, the library can therefore be used for its implementation in standard PHP installations, even if the calculation of Argon2d hashes is not efficient.

Evaluation of the PlainPHPArgon2d library in shared hosting

As the Credential Check checks the user’s credentials in real time during login, it must be possible to calculate the Argon2d hash with the cost parameters of the Credential Check in less than one second. This corresponds to the maximum delay of a login process that should not be exceeded from the user’s point of view.

The following figure shows the calculation times of an Argon2d hash for the Credential Check using the library over the course of a day in the shared hosting of 000webhost and IONOS. The figure shows that despite the inefficient calculation of Argon2d hashes, the library always keeps the calculation times below one second due to the low cost parameters of the Credential Check. This means that the library can be used in practice on all types of web hosting to realise the credential checker and thus actively prevent identity theft.

The figure shows the average calculation times of an Argon2d hash for the Credential Check with the PlainPHPArgon2d library over the course of the day in the shared hosting of 000webhost and IONOS. It can be seen that the calculation times are relatively constant and are always less than 1 second.
Figure: The figure shows the average calculation times of an Argon2d hash for the Credential Check with the PlainPHPArgon2d library over the course of the day in the shared hosting of 000webhost and IONOS. It can be seen that the calculation times are relatively constant and are always less than 1 second.

Due to the efficient calculation of Argon2d hashes, the extension should preferably be used to realise the Credential Check. If the library is nevertheless used for the Credential Check, the Argon2d hash of the user name should be saved permanently together with the password hash in order to reduce delays when logging in. This is possible because the calculated Argon2d hash of the user name is always the same when logging in. The saved Argon2d hash only needs to be updated if the user name is changed.

Conclusion

To summarise, it can be stated that the development of the PHPArgon2d extension and the PlainPHPArgon2d library makes an important contribution to improving the security of users and service providers against identity theft, as they can be actively and preventively protected against it. It should be particularly emphasised that both the PHPArgon2d extension and the PlainPHPArgon2d library have successfully demonstrated their suitability for the practical use of Argon2d in PHP during the evaluation.

About this work

The PHPArgon2d extension and the PlainPHPArgon2d library were developed as part of a bachelor’s thesis at the Rheinische Friedrich-Wilhelms-Universität Bonn in cooperation with Identeco. The source code of the PHPArgon2d extension and the PlainPHPArgon2d library is available on GitHub under the MIT licence.

Contact an Expert

Do you have any further questions or need specific help? Write us a message or arrange a meeting directly.

Show more

Get to the blog