Atualmente sou estudante e estou estudando PHP, estou tentando fazer uma criptografia / descriptografia simples de dados em PHP. Fiz algumas pesquisas online e algumas delas foram bastante confusas (pelo menos para mim).
Aqui está o que estou tentando fazer:
Eu tenho uma tabela que consiste nestes campos (UserID, Fname, Lname, Email, Password)
O que eu quero é ter todos os campos criptografados e, em seguida, ser descriptografados (é possível usar sha256
para criptografia / descriptografia, se não algum algoritmo de criptografia)
Outra coisa que quero aprender é como criar um caminho único hash(sha256)
combinado com um bom "sal". (Basicamente, eu só quero ter uma implementação simples de criptografia / descriptografia, hash(sha256)+salt)
Senhor / Senhora, suas respostas seriam de grande ajuda e serão muito apreciadas. Obrigado ++
fonte
Respostas:
Prefácio
Começando com a definição da sua mesa:
Aqui estão as mudanças:
Fname
,Lname
eEmail
serão criptografados usando uma cifra simétrica, fornecida pelo OpenSSL ,IV
campo armazenará o vetor de inicialização usado para criptografia. Os requisitos de armazenamento dependem da cifra e do modo usado; mais sobre isso mais tarde.Password
campo será hash usando um one-way hash de senha,Encriptação
Cifra e modo
A escolha da melhor cifra e modo de criptografia está além do escopo desta resposta, mas a escolha final afeta o tamanho da chave de criptografia e do vetor de inicialização; para esta postagem, usaremos AES-256-CBC, que tem um tamanho de bloco fixo de 16 bytes e um tamanho de chave de 16, 24 ou 32 bytes.
Chave de encriptação
Uma boa chave de criptografia é um blob binário gerado a partir de um gerador de números aleatórios confiável. O seguinte exemplo seria recomendado (> = 5,3):
Isso pode ser feito uma ou várias vezes (se desejar criar uma cadeia de chaves de criptografia). Mantenha-os o mais privados possível.
IV
O vetor de inicialização adiciona aleatoriedade à criptografia e é necessário para o modo CBC. Idealmente, esses valores devem ser usados apenas uma vez (tecnicamente, uma vez por chave de criptografia), portanto, uma atualização de qualquer parte de uma linha deve gerá-la novamente.
Uma função é fornecida para ajudá-lo a gerar o IV:
Exemplo
Vamos criptografar o campo de nome, usando o anterior
$encryption_key
e$iv
; para fazer isso, temos que preencher nossos dados com o tamanho do bloco:Requisitos de armazenamento
A saída criptografada, como o IV, é binária; o armazenamento desses valores em um banco de dados pode ser realizado usando tipos de coluna designados como
BINARY
ouVARBINARY
.O valor de saída, como o IV, é binário; para armazenar esses valores no MySQL, considere usar as colunas
BINARY
ouVARBINARY
. Se isso não for uma opção, você também pode converter os dados binários em uma representação textual usandobase64_encode()
oubin2hex()
, para fazer isso requer entre 33% a 100% mais espaço de armazenamento.Decifrar
A descriptografia dos valores armazenados é semelhante:
Criptografia autenticada
Você pode melhorar ainda mais a integridade do texto cifrado gerado anexando uma assinatura gerada a partir de uma chave secreta (diferente da chave criptografada) e o texto cifrado. Antes de o texto cifrado ser descriptografado, a assinatura é primeiro verificada (de preferência com um método de comparação de tempo constante).
Exemplo
Veja também:
hash_equals()
Hashing
O armazenamento de uma senha reversível em seu banco de dados deve ser evitado tanto quanto possível; você deseja apenas verificar a senha em vez de saber seu conteúdo. Se um usuário perder a senha, é melhor permitir que ele a redefina em vez de enviar a senha original (certifique-se de que a redefinição da senha só possa ser feita por um período limitado).
Aplicar uma função hash é uma operação unilateral; depois, pode ser usado com segurança para verificação sem revelar os dados originais; para senhas, um método de força bruta é uma abordagem viável para descobri-lo devido ao seu comprimento relativamente curto e escolhas de senhas pobres de muitas pessoas.
Algoritmos de hash, como MD5 ou SHA1, foram feitos para verificar o conteúdo do arquivo em relação a um valor de hash conhecido. Eles são bastante otimizados para tornar essa verificação o mais rápido possível e, ao mesmo tempo, ser precisa. Dado seu espaço de saída relativamente limitado, foi fácil construir um banco de dados com senhas conhecidas e suas respectivas saídas hash, as rainbow tables.
Adicionar um salt à senha antes de fazer o hash tornaria uma tabela de arco-íris inútil, mas os recentes avanços de hardware tornaram as pesquisas de força bruta uma abordagem viável. É por isso que você precisa de um algoritmo de hash deliberadamente lento e simplesmente impossível de otimizar. Ele também deve ser capaz de aumentar a carga para hardware mais rápido sem afetar a capacidade de verificar os hashes de senha existentes para torná-lo à prova de futuro.
Atualmente, existem duas opções populares disponíveis:
Esta resposta usará um exemplo com bcrypt.
Geração
Um hash de senha pode ser gerado assim:
O sal é gerado
openssl_random_pseudo_bytes()
para formar um blob aleatório de dados que é então percorridobase64_encode()
estrtr()
para corresponder ao alfabeto exigido de[A-Za-z0-9/.]
.A
crypt()
função executa o hashing com base no algoritmo ($2y$
para Blowfish), o fator de custo (um fator de 13 leva aproximadamente 0,40s em uma máquina de 3GHz) e o sal de 22 caracteres.Validação
Depois de buscar a linha que contém as informações do usuário, você valida a senha desta maneira:
Para verificar uma senha, você chama
crypt()
novamente, mas passa o hash calculado anteriormente como o valor de sal. O valor de retorno produz o mesmo hash se a senha fornecida corresponder ao hash. Para verificar o hash, geralmente é recomendado usar uma função de comparação de tempo constante para evitar ataques de temporização.Hash de senha com PHP 5.5
PHP 5.5 introduziu as funções de hash de senha que você pode usar para simplificar o método de hash acima:
E verificando:
Veja também:
password_hash()
,password_verify()
fonte
$iv_size = 16;
, eu usaria:$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("AES-256-CBC"))
para indicar o link entre o tamanho do iv para usar com a cifra usada. Você também pode expandir um pouco a necessidade (ou não) depkcs7_pad()
/pkcs7_unpad()
, ou simplesmente simplificar a postagem livrando-se deles e usar "aes-256-ctr". Excelente postagem @ Ja͢ckAcho que isso já foi respondido antes ... mas de qualquer maneira, se você deseja criptografar / descriptografar dados, não pode usar SHA256
fonte
Histórico da resposta e explicação
Para entender esta questão, você deve primeiro entender o que é SHA256. SHA256 é uma função criptográfica de hash . Uma função criptográfica Hash é uma função unilateral, cuja saída é criptograficamente segura. Isso significa que é fácil calcular um hash (equivalente a criptografar dados), mas difícil obter a entrada original usando o hash (equivalente a descriptografar os dados). Visto que usar uma função de hash criptográfico significa que a descriptografia é computacionalmente inviável, portanto, você não pode realizar a descriptografia com SHA256.
O que você deseja usar é uma função bidirecional, mas mais especificamente, uma Block Cipher . Uma função que permite criptografar e descriptografar dados. As funções
mcrypt_encrypt
emcrypt_decrypt
por padrão usam o algoritmo Blowfish. O uso de mcrypt pelo PHP pode ser encontrado neste manual . Também existe uma lista de definições de cifras para selecionar a cifra que o mcrypt usa. Um wiki sobre Blowfish pode ser encontrado na Wikipedia . Uma cifra de bloco criptografa a entrada em blocos de tamanho e posição conhecidos com uma chave conhecida, para que os dados possam ser posteriormente descriptografados usando a chave. Isso é o que o SHA256 não pode fornecer a você.Código
fonte
Aqui está um exemplo usando openssl_encrypt
fonte
mcrypt_create_iv()
, eu usaria:,openssl_random_pseudo_bytes(openssl_cipher_iv_length($encryptionMethod))
desta forma a metodologia funciona para qualquer valor de $ encryptionMethod e usaria apenas a extensão openssl.false
paraopenssl_decrypt()
. Consulte stackoverflow.com/q/41952509/1066234 Como as cifras de bloco, como AES, exigem que os dados de entrada sejam um múltiplo exato do tamanho do bloco (16 bytes para AES), o preenchimento é necessário.fonte
Levei um bom tempo para descobrir como não obter um
false
ao usaropenssl_decrypt()
e criptografar e descriptografar funcionando.Se você deseja passar a string criptografada por meio de um URL, é necessário codificar a string em url:
Para entender melhor o que está acontecendo, leia:
Para gerar chaves de 16 bytes, você pode usar:
Para ver as mensagens de erro do openssl, você pode usar:
echo openssl_error_string();
Espero que ajude.
fonte