Criptografia bidirecional: preciso armazenar senhas que possam ser recuperadas

174

Estou criando um aplicativo que armazena senhas, que o usuário pode recuperar e visualizar. As senhas são para um dispositivo de hardware, portanto, a verificação de hashes está fora de questão.

O que eu preciso saber é:

  1. Como criptografar e descriptografar uma senha no PHP?

  2. Qual é o algoritmo mais seguro para criptografar as senhas?

  3. Onde guardo a chave privada?

  4. Em vez de armazenar a chave privada, é uma boa ideia exigir que os usuários insiram a chave privada sempre que precisarem de uma senha descriptografada? (Os usuários deste aplicativo podem ser confiáveis)

  5. De que maneiras a senha pode ser roubada e descriptografada? Do que eu preciso estar ciente?

HyderA
fonte
1
Nota: O Libsodium agora está compilado no núcleo do PHP para> = 7.2. Essa seria a solução "ir para" agora, pois está cheia de métodos modernos, ao contrário do mcrypt, que é considerado obsoleto e foi removido.
exhibitioner

Respostas:

212

Pessoalmente, eu usaria mcryptcomo outros postados. Mas há muito mais a ser observado ...

  1. Como criptografar e descriptografar uma senha no PHP?

    Veja abaixo uma classe forte que cuida de tudo para você:

  2. Qual é o algoritmo mais seguro para criptografar as senhas?

    mais seguro ? qualquer um deles. O método mais seguro para criptografar é proteger contra vulnerabilidades de divulgação de informações (XSS, inclusão remota etc.). Se sair, o invasor pode eventualmente quebrar a criptografia (nenhuma criptografia é 100% reversível sem a chave - como @NullUserException indica que isso não é totalmente verdade. Existem alguns esquemas de criptografia impossíveis de decifrar, como o OneTimePad ) .

  3. Onde guardo a chave privada?

    O que eu faria é usar 3 chaves. Um é fornecido pelo usuário, um é específico ao aplicativo e o outro é específico ao usuário (como um sal). A chave específica do aplicativo pode ser armazenada em qualquer lugar (em um arquivo de configuração fora da raiz da web, em uma variável ambiental, etc.). O específico do usuário seria armazenado em uma coluna no banco de dados próximo à senha criptografada. O usuário fornecido não seria armazenado. Então, você faria algo assim:

    $key = $userKey . $serverKey . $userSuppliedKey;

    O benefício é que qualquer uma das duas chaves pode ser comprometida sem que os dados sejam comprometidos. Se houver um ataque de injeção SQL, eles podem obter o $userKey, mas não o outro 2. Se houver uma exploração do servidor local, eles podem obter $userKeye $serverKey, mas não o terceiro $userSuppliedKey. Se eles baterem no usuário com uma chave inglesa, poderão obter o $userSuppliedKey, mas não os outros 2 (mas, novamente, se o usuário for espancado com uma chave inglesa, você será tarde demais).

  4. Em vez de armazenar a chave privada, é uma boa ideia exigir que os usuários insiram a chave privada sempre que precisarem de uma senha descriptografada? (Os usuários deste aplicativo podem ser confiáveis)

    Absolutamente. De fato, essa é a única maneira de fazê-lo. Caso contrário, você precisará armazenar uma versão não criptografada em um formato de armazenamento durável (memória compartilhada, como APC ou memcached, ou em um arquivo de sessão). Isso está se expondo a compromissos adicionais. Nunca armazene a versão não criptografada da senha em nada, exceto em uma variável local.

  5. De que maneiras a senha pode ser roubada e descriptografada? Do que eu preciso estar ciente?

    Qualquer forma de comprometimento de seus sistemas permitirá que eles visualizem dados criptografados. Se eles puderem injetar código ou acessar o sistema de arquivos, poderão visualizar os dados descriptografados (já que podem editar os arquivos que descriptografam os dados). Qualquer forma de ataque Replay ou MITM também lhes dará acesso total às chaves envolvidas. Farejar o tráfego HTTP bruto também fornecerá as chaves.

    Use SSL para todo o tráfego. E verifique se nada no servidor possui algum tipo de vulnerabilidade (CSRF, XSS, Injeção de SQL, Escalação de Privilégios, Execução Remota de Código, etc.).

Edit: Aqui está uma implementação de classe PHP de um método de criptografia forte:

/**
 * A class to handle secure encryption and decryption of arbitrary data
 *
 * Note that this is not just straight encryption.  It also has a few other
 *  features in it to make the encrypted data far more secure.  Note that any
 *  other implementations used to decrypt data will have to do the same exact
 *  operations.  
 *
 * Security Benefits:
 *
 * - Uses Key stretching
 * - Hides the Initialization Vector
 * - Does HMAC verification of source data
 *
 */
class Encryption {

    /**
     * @var string $cipher The mcrypt cipher to use for this instance
     */
    protected $cipher = '';

    /**
     * @var int $mode The mcrypt cipher mode to use
     */
    protected $mode = '';

    /**
     * @var int $rounds The number of rounds to feed into PBKDF2 for key generation
     */
    protected $rounds = 100;

    /**
     * Constructor!
     *
     * @param string $cipher The MCRYPT_* cypher to use for this instance
     * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
     * @param int    $rounds The number of PBKDF2 rounds to do on the key
     */
    public function __construct($cipher, $mode, $rounds = 100) {
        $this->cipher = $cipher;
        $this->mode = $mode;
        $this->rounds = (int) $rounds;
    }

    /**
     * Decrypt the data with the provided key
     *
     * @param string $data The encrypted datat to decrypt
     * @param string $key  The key to use for decryption
     * 
     * @returns string|false The returned string if decryption is successful
     *                           false if it is not
     */
    public function decrypt($data, $key) {
        $salt = substr($data, 0, 128);
        $enc = substr($data, 128, -64);
        $mac = substr($data, -64);

        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        if (!hash_equals(hash_hmac('sha512', $enc, $macKey, true), $mac)) {
             return false;
        }

        $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

        $data = $this->unpad($dec);

        return $data;
    }

    /**
     * Encrypt the supplied data using the supplied key
     * 
     * @param string $data The data to encrypt
     * @param string $key  The key to encrypt with
     *
     * @returns string The encrypted data
     */
    public function encrypt($data, $key) {
        $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        $data = $this->pad($data);

        $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

        $mac = hash_hmac('sha512', $enc, $macKey, true);
        return $salt . $enc . $mac;
    }

    /**
     * Generates a set of keys given a random salt and a master key
     *
     * @param string $salt A random string to change the keys each encryption
     * @param string $key  The supplied key to encrypt with
     *
     * @returns array An array of keys (a cipher key, a mac key, and a IV)
     */
    protected function getKeys($salt, $key) {
        $ivSize = mcrypt_get_iv_size($this->cipher, $this->mode);
        $keySize = mcrypt_get_key_size($this->cipher, $this->mode);
        $length = 2 * $keySize + $ivSize;

        $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

        $cipherKey = substr($key, 0, $keySize);
        $macKey = substr($key, $keySize, $keySize);
        $iv = substr($key, 2 * $keySize);
        return array($cipherKey, $macKey, $iv);
    }

    /**
     * Stretch the key using the PBKDF2 algorithm
     *
     * @see http://en.wikipedia.org/wiki/PBKDF2
     *
     * @param string $algo   The algorithm to use
     * @param string $key    The key to stretch
     * @param string $salt   A random salt
     * @param int    $rounds The number of rounds to derive
     * @param int    $length The length of the output key
     *
     * @returns string The derived key.
     */
    protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
        $size   = strlen(hash($algo, '', true));
        $len    = ceil($length / $size);
        $result = '';
        for ($i = 1; $i <= $len; $i++) {
            $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
            $res = $tmp;
            for ($j = 1; $j < $rounds; $j++) {
                 $tmp  = hash_hmac($algo, $tmp, $key, true);
                 $res ^= $tmp;
            }
            $result .= $res;
        }
        return substr($result, 0, $length);
    }

    protected function pad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $padAmount = $length - strlen($data) % $length;
        if ($padAmount == 0) {
            $padAmount = $length;
        }
        return $data . str_repeat(chr($padAmount), $padAmount);
    }

    protected function unpad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $last = ord($data[strlen($data) - 1]);
        if ($last > $length) return false;
        if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
            return false;
        }
        return substr($data, 0, -1 * $last);
    }
}

Note que eu estou usando uma função adicionado no PHP 5.6: hash_equals. Se você estiver com menos de 5,6, poderá usar esta função substituta que implementa uma função de comparação com tempo seguro usando a verificação dupla do HMAC :

function hash_equals($a, $b) {
    $key = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    return hash_hmac('sha512', $a, $key) === hash_hmac('sha512', $b, $key);
}

Uso:

$e = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$encryptedData = $e->encrypt($data, $key);

Então, para descriptografar:

$e2 = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, $key);

Observe que eu usei $e2a segunda vez para mostrar que diferentes instâncias ainda decifrariam os dados corretamente.

Agora, como funciona / por que usá-lo em outra solução:

  1. Chaves

    • As chaves não são usadas diretamente. Em vez disso, a chave é esticada por uma derivação PBKDF2 padrão.

    • A chave usada para criptografia é exclusiva para cada bloco de texto criptografado. A chave fornecida torna-se, portanto, uma "chave mestra". Essa classe, portanto, fornece rotação de chaves para chaves de cifra e autenticação.

    • NOTA IMPORTANTE , o $roundsparâmetro está configurado para chaves aleatórias verdadeiras com força suficiente (128 bits de aleatório Criptograficamente seguro no mínimo). Se você for usar uma senha ou chave não aleatória (ou menos aleatória que 128 bits de CS aleatória), deverá aumentar este parâmetro. Eu sugeriria um mínimo de 10000 para senhas (quanto mais você puder pagar, melhor, mas isso aumentará o tempo de execução) ...

  2. Integridade de dados

    • A versão atualizada usa ENCRYPT-THEN-MAC, que é um método muito melhor para garantir a autenticidade dos dados criptografados.
  3. Criptografia:

    • Ele usa mcrypt para realmente executar a criptografia. Eu sugeriria o uso de um MCRYPT_BLOWFISHou de MCRYPT_RIJNDAEL_128códigos e MCRYPT_MODE_CBCpara o modo. É forte o suficiente e ainda bastante rápido (um ciclo de criptografia e descriptografia leva cerca de 1/2 segundo na minha máquina).

Agora, como no ponto 3 da primeira lista, o que isso daria a você é uma função como esta:

function makeKey($userKey, $serverKey, $userSuppliedKey) {
    $key = hash_hmac('sha512', $userKey, $serverKey);
    $key = hash_hmac('sha512', $key, $userSuppliedKey);
    return $key;
}

Você pode esticá-lo na makeKey()função, mas como ele será expandido mais tarde, não há realmente um grande ponto em fazê-lo.

Quanto ao tamanho do armazenamento, isso depende do texto sem formatação. O Blowfish usa um tamanho de bloco de 8 bytes, então você terá:

  • 16 bytes para o sal
  • 64 bytes para o hmac
  • comprimento dos dados
  • Preenchimento para que o comprimento dos dados% 8 == 0

Portanto, para uma fonte de dados de 16 caracteres, haverá 16 caracteres a serem criptografados. Isso significa que o tamanho real dos dados criptografados é de 16 bytes devido ao preenchimento. Em seguida, adicione 16 bytes para o salt e 64 bytes para o hmac e o tamanho total armazenado é 96 bytes. Portanto, há no máximo uma sobrecarga de 80 caracteres e, na pior, uma sobrecarga de 87 caracteres ...

Espero que ajude ...

Nota: 12/11/12: Acabei de atualizar esta classe com um método de criptografia MUITO melhor, usando chaves derivadas melhores e corrigindo a geração MAC ...

ircmaxell
fonte
3
Alguém não entende o que significa "pausa". Bom trabalho do @IRC na classe, é um ótimo código.
precisa saber é o seguinte
1
O seguinte retorna false. Alguma idéia do porquê? $ x = nova criptografia (MCRYPT_BlOWFISH, MCRYPT_MODE_CBC); $ test = $ x-> encrypt ("teste", "a"); echo var_dump ($ x-> descriptografar ($ test, "a"));
O comprimento de onda
2
Ah, e mais uma vez na função decrypt mudando os dois -64s a -128ajudou (de modo a obter $enc = substr($data, 128, -128)e$mac = substr($data, -128);
cosmorogers
4
@ircmaxell Já faz um bom tempo desde que o código foi revisado pela última vez, então estou me perguntando se está atualizado. Eu preciso usar algo semelhante para uma aplicação financeira e que seria bom se você deu um bem com esta classe :-)
nt.bas
2
Aviso! A extensão mcrypt é abandonware há quase uma década e também era bastante complexa de usar. Portanto, foi preterido em favor do OpenSSL, onde será removido do núcleo e para o PECL no PHP 7.2. th1.php.net/manual/en/migration71.deprecated.php
vee
15

Como criptografar e descriptografar uma senha no PHP? Implementando um dos muitos algoritmos de criptografia. (ou usando uma das muitas bibliotecas)

Qual é o algoritmo mais seguro para criptografar as senhas? Existem vários algoritmos diferentes, nenhum dos quais é 100% seguro. Mas muitos deles são seguros o suficiente para o comércio e até para fins militares

Onde guardo a chave privada? Se você decidiu implementar o algoritmo de criptografia de chave pública (por exemplo, RSA), não armazena chave privada. usuário tem chave privada. seu sistema possui uma chave pública que pode ser armazenada em qualquer lugar que você desejar.

Em vez de armazenar a chave privada, é uma boa ideia exigir que os usuários insiram a chave privada sempre que precisarem de uma senha descriptografada? (Os usuários deste aplicativo podem ser confiáveis) Bem, se o usuário puder se lembrar de números primos ridiculamente longos, então - sim, por que não. Mas geralmente você precisa criar o sistema que permitirá ao usuário armazenar sua chave em algum lugar.

De que maneiras a senha pode ser roubada e descriptografada? Do que eu preciso estar ciente? Isso depende do algoritmo usado. No entanto, sempre verifique se você não envia uma senha não criptografada para ou do usuário. Criptografe / descriptografe no lado do cliente ou use https (ou outro meio criptográfico do usuário para proteger a conexão entre servidor e cliente).

No entanto, se tudo o que você precisa é armazenar senhas de maneira criptografada, sugiro que você use uma cifra XOR simples. O principal problema desse algoritmo é que ele pode ser facilmente quebrado pela análise de frequência. No entanto, como geralmente as senhas não são feitas de longos parágrafos do texto em inglês, acho que você não deve se preocupar com isso. O segundo problema com o XOR Cipher é que, se você tiver uma mensagem no formato criptografado e descriptografado, poderá descobrir facilmente a senha com a qual foi criptografada. Novamente, não é um grande problema no seu caso, pois afeta apenas o usuário que já foi comprometido por outros meios.

Ivan
fonte
Na resposta 3, quando você diz que os usuários têm chave privada, não entendo o que isso significa. Você não recomenda passar manualmente as chaves privadas para o aplicativo pelo usuário; então, de que outra forma as chaves privadas são passadas para o aplicativo?
HyderA
Bem, isso é um pouco de problema. A chave privada pode ser armazenada no arquivo de texto e copiada e colada no aplicativo. A chave também pode ser armazenada no servidor, mas, nesse caso, ainda deve ser criptografada com outro algoritmo de criptografia como o XOR. O uso do XOR aqui neste caso é seguro o suficiente, pois há apenas um par de senha e mensagem e a mensagem é bastante aleatória, portanto, a análise de frequência fria não deve ser usada.
Ivan
4
Eu certamente não recomendaria a implementação de um algoritmo de criptografia, existem muitas armadilhas em potencial e as bibliotecas existentes foram testadas e analisadas por muitas pessoas.
orelhas longas
O principal problema do XOR é que, se alguém rouba os dados do aplicativo e conhece apenas uma das senhas de um usuário, pode descriptografar todas as outras senhas para esse usuário.
orelhas longas
1
@ Ivan: sim, mas este é um dos casos em que eu acho que o DIY é realmente muito ruim, a menos que você realmente entenda a criptografia. Existem cifras fortes que existem, por que não usá-las?
precisa saber é o seguinte
13
  1. A função PHP que você procura é o Mcrypt ( http://www.php.net/manual/en/intro.mcrypt.php ).

O exemplo do manual é ligeiramente editado para este exemplo):

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$pass = "PasswordHere";
echo strlen($pass) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $pass, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
?>

Você usaria mcrypt_decrypt para descriptografar sua senha.

  1. O melhor algoritmo é bastante subjetivo - pergunte a 5 pessoas, obtenha 5 respostas. Pessoalmente, se o padrão (Blowfish) não for bom o suficiente para você, você provavelmente terá problemas maiores!

  2. Dado que o PHP é necessário para criptografar - não tendo certeza de que você pode ocultá-lo em qualquer lugar - dê boas-vindas aos comentários sobre isso. As melhores práticas de codificação PHP padrão se aplicam, é claro!

  3. Dado que a chave de criptografia estará no seu código de qualquer maneira, não tenha certeza do que você ganhará, desde que o restante do seu aplicativo seja seguro.

  4. Obviamente, se a senha criptografada e a chave de criptografia forem roubadas, o jogo termina.

Eu colocaria um piloto na minha resposta - não sou especialista em criptografia PHP, mas acho que o que respondi é uma prática padrão - congratulo-me com comentários que outros possam ter.

Jon Rhoades
fonte
$pass = $text. Acho que ele mudou isso para atender à pergunta e não percebeu a segunda ocorrência.
HyderA
3
Duas coisas a serem observadas. Primeiro, MCRYPT_MODE_ECBnão usa um IV. Em segundo lugar, se o fizesse, seria necessário para armazenar o IV como você não pode descriptografar os dados sem ele ...
ircmaxell
"O melhor algoritmo é bastante subjetivo - pergunte a 5 pessoas, obtenha 5 respostas. Pessoalmente, se o padrão (Blowfish) não for bom o suficiente para você, você provavelmente terá problemas maiores!" Isso está totalmente errado. Qualquer especialista de criptografia será mais ou menos de acordo com gist.github.com/tqbf/be58d2d39690c3b366ad que exclui especificamente Blowfish
Scott Arciszewski
6

Muitos usuários sugeriram o uso do mcrypt ... o que é correto, mas eu gosto de ir um pouco mais longe para torná-lo facilmente armazenado e transferido (já que às vezes os valores criptografados podem dificultar o envio usando outras tecnologias como curl ou json) .

Depois de criptografar com sucesso usando mcrypt, execute-o através do base64_encode e converta-o em código hexadecimal. Uma vez no código hexadecimal, é fácil transferir de várias maneiras.

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $unencrypted);
$encrypted = $ua."||||".$iv;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$encrypted = base64_encode($encrypted);
$encrypted = array_shift(unpack('H*', $encrypted));

E do outro lado:

$encrypted = pack('H*', $encrypted);
$encrypted = base64_decode($encrypted);
list($encrypted,$iv) = explode("||||",$encrypted,2);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$unencrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
Bradley
fonte
2
Bem - foi em 2011: P
Bradley
5

Eu sugeriria apenas a criptografia de chave pública se você quiser definir a senha de um usuário sem a interação (isso pode ser útil para redefinições e senhas compartilhadas).

Chave pública

  1. A extensão OpenSSL , especificamente openssl_public_encrypteopenssl_private_decrypt
  2. Isso seria um RSA direto, assumindo que suas senhas cabem no tamanho da chave - preenchimento, caso contrário, você precisará de uma camada simétrica
  3. Armazene as duas chaves para cada usuário, a senha da chave privada é a senha do aplicativo

Simétrico

  1. A extensão Mcrypt
  2. O AES-256 é provavelmente uma aposta segura, mas isso pode ser uma questão SO por si só
  3. Você não - essa seria a senha do aplicativo

Ambos

4. Sim - os usuários precisariam digitar a senha do aplicativo toda vez, mas armazená-la na sessão geraria outros problemas

5.

  • Se alguém rouba os dados do aplicativo, é tão seguro quanto a cifra simétrica (para o esquema de chave pública, é usado para proteger a chave privada com a senha).
  • Seu aplicativo definitivamente deve ser acessível apenas por SSL, de preferência usando certificados de cliente.
  • Considere adicionar um segundo fator para autenticação que seria usado apenas uma vez por sessão, como um token enviado via SMS.
Orelhas longas
fonte
Evite mcrypt, tenha cuidado com openssl_private_decrypt().
Scott Arciszewski
2

Eu tentei algo parecido com isto, mas observe que não sou criptografador nem tenho profundo conhecimento sobre phpou qualquer linguagem de programação. É apenas uma ideia. Minha idéia é armazenar keyem algum arquivo ou database(ou inserir manualmente) que (local) não possa ser facilmente previsto (e, é claro, qualquer coisa será descriptografada algum dia, o conceito é aumentar o tempo de descriptografia) e criptografar informações confidenciais.

$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH , MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "evenifyouaccessmydatabaseyouwillneverfindmyemail";
$text = "[email protected]";
echo "Key : ".$key."<br/>";
echo "Text : ".$text . "<br/>";
echo "Md5 : ".md5($text). "<br/>";
echo "Sha1 : ".sha1($text). "<br/>";



$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH , $key, $text, MCRYPT_MODE_ECB, $iv);
echo "Crypted Data : ".$crypttext."<br>";

$base64 = base64_encode($crypttext);
echo "Encoded Data : ".$base64."<br/>";
$decode =  base64_decode($base64);


$decryptdata = mcrypt_decrypt(MCRYPT_BLOWFISH , $key, $crypttext, MCRYPT_MODE_ECB, $iv);

echo "Decoded Data : ".ereg_replace("?", null ,  $decryptdata); 
//event if i add '?' to the sting to the text it works, I don't know why.

Por favor, note que é apenas um conceito. Qualquer melhoria neste código seria altamente apreciável.

Santosh Linkha
fonte
2

As senhas são para um dispositivo de hardware, portanto, a verificação de hashes está fora de questão.

Eh? Eu não entendo Você quer dizer apenas que a senha deve ser recuperável?

Como outros já disseram, a extensão mcrypt fornece acesso a muitas funções criptográficas - no entanto, você está convidando seus usuários a colocar todos os ovos em uma cesta - uma que será potencialmente um alvo para os invasores - e se você nem sabe como começar a resolver o problema, você estará fazendo um desserviço aos usuários. Você não está em posição de entender como proteger os dados.

A maioria das vulnerabilidades de segurança ocorre não porque o algoritmo subjacente é defeituoso ou inseguro - mas devido a problemas com a maneira como o algoritmo é usado no código do aplicativo.

Dito isto, é possível construir um sistema razoavelmente seguro.

Você deve considerar a criptografia assimétrica apenas se precisar de um usuário para criar uma mensagem segura que seja legível por outro usuário (específico). A razão é que é computacionalmente caro. Se você deseja apenas fornecer um repositório para que os usuários insiram e recuperem seus próprios dados, a criptografia simétrica é adequada.

Se, no entanto, você armazenar a chave para descriptografar a mensagem no mesmo local da mensagem criptografada (ou onde a mensagem criptografada está armazenada), o sistema não estará seguro. Use o mesmo token para autenticar o usuário e para a chave de descriptografia (ou, no caso de criptografia assimétrica, use o token como a senha da chave privada). Como você precisará armazenar o token no servidor em que a descriptografia ocorre pelo menos temporariamente, considere usar um substrato de armazenamento de sessão não pesquisável ou passar o token diretamente para um daemon associado à sessão que armazenaria o token na memória e execute a descriptografia de mensagens sob demanda.

symcbean
fonte
1

Use password_hash e password_verify

<?php
/**
 * In this case, we want to increase the default cost for BCRYPT to 12.
 * Note that we also switched to BCRYPT, which will always be 60 characters.
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

E para descriptografar:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
?>
jvitoroc
fonte