Best way to use AES encryption

4

Well, let's say I'm working on a system where the encryption key is derived from the user's password (something like what KeePass does), in that case I have three questions:

Which algorithm to use to derive the key? So that it is as far as possible from the password and that it always has 256 BIT?

And if the user redefines his password, what happens to the key and the already encrypted data? remembering that all data (from him, customer information, etc ...) will be encrypted in a way that only he has access to the original information when logging into the system, in that sense neither I (programmer) could recover the data even if he wanted to. Another detail is that this is a system that only one user will access, but will have a considerable amount of data.

And finally, is this feasible? or would it be better for me to generate a "Master" Key that only he would have to store and then enter the password next time I log into a new device? Just like what 1Password does.

PS: with store I mean remember / save.

    
asked by anonymous 30.09.2017 / 16:51

1 answer

3
  

Which algorithm to use to derive the key? So that it is as far as possible from the password and that it always has 256 BIT?

The "best" is Argon2i which is available in PHP 7.2 (or via PECL). But as you may not have LibSodium, you have other options.

You have hash_pbkdf2 available in PHP 5.5, it uses PBKDF2. Briefly, PBKDF2 does a loop of HMAC, using a salt and user input, this does the key derivation. It has a customizable length, there is a maximum based on the algorithm used, except for cheating, as well as the HKDF (which is hash_hkdf ).

The existence of a number of iterations delays the discovery of the password, since dictionary (and related) attacks will slow down as the difficulty is greater and also "farther" from the original entry. By default, PBKDF2 uses SHA-1, but this is not recommended, use newer, more reliable hashing algorithms (SHA-3, SHA-2, or BLAKE).

string hash_pbkdf2 ( string $algo , string $password , string $salt , int $iterations [, int $length = 0 [, bool $raw_output = false ]] )

Example:

$sal = random_bytes(16); // 128-Bits de salt
$iteracoes = 250000; // 250 000 iterações
$tamanho = 256;

if($sal !== false){
    $hash = hash_pbkdf2(
        "sha384", // SHA-2 de 384 bits
        $senha, // Sua senha
        $sal,
        $iteracoes,
        $tamanho,
        true);
}

However, the best option is in LibSodium, which is sodium_crypto_pwhash , it uses the algorithm that was the winner of PHC . , Argon 2i. Its use is similar to PBKDF2, with the difference that we have more options than just choosing the amount of "iterations".

string sodium_crypto_pwhash(int $output_length, string $password, string $salt, int $opslimit, int $memlimit)

Example:

$sal = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES);
$tamanho = 256;
$limiteOperacoes = 32; // 8 vezes maior que o padrão
$limiteMemoria = 1<<27; // 4 vezes maior que o padrão

if($sal !== false){
    $hash = sodium_crypto_pwhash(
        $tamanho,
        $senha, // Sua senha
        $sal,
        $limiteOperacoes,
        $limiteMemoria
    );
}

The value of opslimit and memlimit can be obtained by SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE and SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE , they are secure bases, the greater this supposedly the better. The first value will require more CPU power, more cycles. The second one will require more memory.

However, using weak passwords (alias 123456789) will not have a saving path.

You can also use SCrypt, but I have never used this in PHP and there are no plans to be natively supported in PHP.

Since passwords are sensitive, they should not stay in memory for a long time, so after the derivation use:

sodium_memzero($senha);
  

And if the user redefines his password, what happens to the key and the already encrypted data?

Simple. Simply "decrypt" the old password and then encrypt it with the result of deriving the new password.

If the user does not know the current password, which is currently used, it already was. It's better that he loses access to data than anyone else has. ;)

  

And finally, is this feasible? or would I rather generate a "Master" Key that only he would have to store and then report every time I log into a new device? Just like what 1Password does.

I do not know how 1Password works, but I very much doubt that it uses only a "Master Key". Possibly it has a password (chosen by the user) and a key, together they can be used to derive a new key or each one (the password and the key) are used for a different purpose, or the password is used to decrypt itself key. What I believe (this is totally a kick) is that everyone has a purpose, their password (and their derivation) is for encryption / decryption, while the master key is for authentication, to prove that you are who you say you are.

These are different purposes, but this is just a kick. Maybe 1Password has some public information on how it works, but I did not find it.

    
01.10.2017 / 01:00