Best Way to Use AES Encryption

Asked

Viewed 1,005 times

4

Guys, 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 which case I have three questions:

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

And if the user re-sets his password, what would happen to the key and the already encrypted data? recalling that all data (from it, customer information, etc...) will be encrypted in such a way that only it has access to the original information when logging into the system, in this sense not even I (programmer) could recover the data even if I 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 lastly, is that viable? or would it be better for me to generate a "Master" Key that only he would have to store and then inform next to the password every time he logs into a new device? Just like what 1Password does.

PS: By storing I mean remembering/saving.

1 answer

3


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

"Best" is Argon2i which is available in PHP 7.2 (or via PECL). But since you may not have Libsodium, there are other options.

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

The fact that it exists at a number of iterations delays the discovery of the password, since dictionary attacks (and the like) will be slower as the difficulty increases and also "farther" from the original input. By default PBKDF2 uses SHA-1, but this is not recommended, use more recent and 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 the sodium_crypto_pwhash, it uses the algorithm that was the winner of PHC, Argon2i. 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 opslimitand the memlimit standard can be obtained by SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE and SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE, they are safe bases, the higher that supposedly better. The first value will require higher CPU power, higher amount of cycles. The second will require more memory.

However, using weak passwords (Alá 123456789) will not have derivation to save.

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

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

sodium_memzero($senha);

And if the user re-sets his password, what would happen with the key and the already encrypted data?

Simple. Just "decrypt" with the old password and then encrypt with the result of the derivation of the new password.

If the user does not know the current password, which is currently used, it is gone. It is better that he loses access to the data than anyone having. ;)

And lastly, is that viable? or would it be better for me to generate a "Master" Key that only he would have to store and then inform him every time he logs into a new device? Just like what 1Password does.

I don’t know how 1Password works, but I highly doubt that it uses only a "Master Key". Possibly it has a password (chosen by the user) and a key, together can be used to derive a new key or each one (the password and the key) are used for a different purpose, or even the password serves to decrypt the key itself. What I believe (this is totally a kick) is that each one has a purpose, its password (and its derivation) serves to encrypt/decrypt, while the master key serves for authentication, to prove that you are who you say you are.

These are different purposes, but this is just a guess. Maybe 1Password has some public information on how it works, but I didn’t find.

  • His explanation was very enlightening, in this case I will use the derivation of the password itself, but I will "force" the user to create a more secure password, as he himself required the system to be "safe" no problem I force him to create a more elaborate password.

  • I really forgot to mention that it uses Master Key + User Password. They explain the basic flow, but I also found no specific documentation. As I have an account in him I know that he generates this Master Key only once and leaves on my account her "safety". The login is done stating both Password and Master Key. There’s a part that mentions that the Master Key is the "evolution" (or something like that) of authentication in 2 factors, so I would say that your kick should be right.

  • Only complementary for those interested in 1Password, I found this document of them, really very complete: https://1password.com/files/1Password%20for%20Teams%20White%20Paper.pdf

Browser other questions tagged

You are not signed in. Login or sign up in order to post.