Search code examples
phpstring-hashing

Can i use PASSWORD_HASH for login names?


I want to have a pretty secure login on my website. I decided to use 3 inputs for my form. Login name and password to log into your account and a Username that will be shown on the website. So if someone gets access to the table, he will need to brute force the Login and the Password.

Can and should i use password_hash() for the Login name or should i use normal hash() -ing ?


Solution

  • What you will most likely end up doing is having two tables.

    One table will contain the user's data, ie a unique user id, user name, name, email ect. The username, name, email, will all be encrypted.

    The second table will be a hash table. This is the table that you will use to verify the user's username and password. It should have the unique user id, a hashed(no IV) value of the username, and then your password which you will use password_verify() to validate.

    When your user logs in they will provide their username and a password. The username will be hashed by the same process with no IV as to allow the hash to always equal the hash that is stored on the hash table for that user's username. This will allow you to query for the appropriate record to check the password. Check your password with the password_verify() function.

    Once the username and password check out you have verified that your user has the appropriate credentials you will make a second query using the unique user id on the first table. When your query returns the data it will be the encrypted values for that user, decrypt and you are ready to display the user's info to the user.

    If I get access to your tables I will never see any of your user's information. I would be able to see the unique users id and see that the id matches the id on both tables, but that being said all the values are either hashed or encrypted.

    I would highly recommend using the Libsodium Library to do the hashing and encrypting. (Let the native php password functions take care of all your password stuff.) Libsodium is now supported natively on the lastest PHP versions.

    It is suggested that your tables and your server's file directories are on two physically different machines. This is because you will be storing the encryption keys in your directory, ideally below your root directory. If your server is compromised they do not have direct access to you tables and if your tables are compromised they do not have access to your keys.

    Hopefully this gets you going in the right direction.

    Updated

    Here is a simple encrypt/decrypt routine that will encrypt the user name without an IV. This means that as long as the key remains the same it will encrypt the same plain text to the same cipher text every time. This will allow for you to query the cipher text against the same cipher text in your database.

    define("MYKEY_", base64_decode('LoPCPKd8iDxHvb8mATzhhg=='));
    
    function encryptName($plainText) {
    
      return base64_encode(openssl_encrypt($plainText, 'AES-128-CBC', MYKEY_, OPENSSL_RAW_DATA, NULL));
    
    }
    
    function decryptName($cipherText) {
    
      return openssl_decrypt(base64_decode($cipherText), 'AES-128-CBC', MYKEY_, OPENSSL_RAW_DATA, NULL);
    
    }
    
    
    $text = 'myUserName';
    
    $cipherText = encryptName($text);
    echo $cipherText . '<br>';
    
    $plainText = decryptName($cipherText);
    echo $plainText;