Como você criptografa e descriptografa uma string PHP?

225

O que eu quero dizer é:

Original String + Salt or Key --> Encrypted String
Encrypted String + Salt or Key --> Decrypted (Original String)

Talvez algo como:

"hello world!" + "ABCD1234" --> Encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, for e.g)
"2a2ffa8f13220befbe30819047e23b2c" --> Decrypt with "ABCD1234" --> "hello world!"
  • Em PHP, como você pode fazer isso?

Tentou usar Crypt_Blowfish, mas não funcionou para mim.

夏 期 劇場
fonte
35
@ Rogue Ele não quer um hash, ele quer criptografia simétrica (como o AES), ele simplesmente não sabe como é chamado. (E agora ele faz :))
Patashu
Quão seguro ele precisa ser?
3
@ 夏 期 劇場, você não 'salta' a criptografia simétrica, usa uma chave. Uma chave deve ser mantida em segredo. Um salt pode ser público sem prejudicar a segurança (contanto que o sal de todos seja diferente) e é um termo usado no hash de senhas.
Patashu 17/05
2
Você precisa de um Salt (chave privada), uma chave pública e um algoritmo de criptografia como o AES-256: wpy.me/blog/15-encrypt-and-decrypt-data-in-php-using-aes-256
wappy
8
@CristianFlorea O autor dessa publicação no blog usa termos que simplesmente não fazem o menor sentido no contexto da criptografia simétrica. Não há chave pública com a AES, nem há sal. Há uma única chave; deve ser mantido em segredo. Em alguns modos de operação, existe um IV que não precisa ser secreto, mas um IV não é um sal (dependendo do modo, pode ter requisitos bem diferentes) e não precisa ser secreto, enquanto a chave de criptografia real não pode ser absolutamente pública. A chave pública / privada se aplica à criptografia assimétrica, mas não tem nada a ver com o AES.
cpast

Respostas:

410

Antes de fazer algo mais, procure entender a diferença entre criptografia e autenticação e por que você provavelmente deseja criptografia autenticada em vez de apenas criptografia .

Para implementar a criptografia autenticada, você deseja criptografar e depois o MAC. A ordem de criptografia e autenticação é muito importante! Uma das respostas existentes para essa pergunta cometeu esse erro; assim como muitas bibliotecas de criptografia escritas em PHP.

Você deve evitar implementar sua própria criptografia e, em vez disso, usar uma biblioteca segura criada e revisada por especialistas em criptografia.

Atualização: o PHP 7.2 agora fornece libsodium ! Para melhor segurança, atualize seus sistemas para usar o PHP 7.2 ou superior e siga apenas os conselhos de libsodium nesta resposta.

Use libsodium se você tiver acesso ao PECL (ou sodium_compat se desejar libsodium sem PECL); caso contrário ...
Use defuse / php-encryption ; não role sua própria criptografia!

Ambas as bibliotecas vinculadas acima acima tornam fácil e simples implementar a criptografia autenticada em suas próprias bibliotecas.

Se você ainda deseja escrever e implantar sua própria biblioteca de criptografia, contra a sabedoria convencional de todo especialista em criptografia na Internet, estas são as etapas que você deve executar.

Criptografia:

  1. Criptografar usando AES no modo CTR. Você também pode usar o GCM (que remove a necessidade de um MAC separado). Além disso, ChaCha20 e Salsa20 (fornecidos pela libsodium ) são cifras de fluxo e não precisam de modos especiais.
  2. A menos que você tenha escolhido o GCM acima, você deve autenticar o texto cifrado com HMAC-SHA-256 (ou, para as cifras de fluxo, Poly1305 - a maioria das APIs de libsódio faz isso por você). O MAC deve cobrir tanto o IV quanto o texto cifrado!

Descriptografia:

  1. A menos que Poly1305 ou GCM seja usado, recalcule o MAC do texto cifrado e compare-o com o MAC que foi enviado usando hash_equals(). Se falhar, aborte.
  2. Descriptografe a mensagem.

Outras considerações de design:

  1. Nunca comprima nada. O texto cifrado não é compactável; compactar texto sem formatação antes da criptografia pode levar a vazamentos de informações (por exemplo, CRIME e BREACH on TLS).
  2. Certifique-se de usar mb_strlen()e mb_substr(), usando o '8bit'modo de conjunto de caracteres para evitar mbstring.func_overloadproblemas.
  3. IVs devem ser gerados usando um CSPRNG ; Se você estiver usando mcrypt_create_iv(), NÃO USEMCRYPT_RAND !
  4. A menos que você esteja usando uma construção AEAD, SEMPRE criptografa o MAC!
  5. bin2hex(), base64_encode()etc. podem vazar informações sobre suas chaves de criptografia via tempo de cache. Evite-os, se possível.

Mesmo se você seguir o conselho dado aqui, muita coisa pode dar errado com a criptografia. Sempre tenha um especialista em criptografia revisando sua implementação. Se você não tiver a sorte de ser amigo pessoal de um estudante de criptografia da sua universidade local, sempre poderá tentar o fórum do Cryptography Stack Exchange para obter orientação.

Se você precisar de uma análise profissional de sua implementação, sempre poderá contratar uma equipe respeitável de consultores de segurança para revisar seu código de criptografia PHP (divulgação: meu empregador).

Importante: Quando não usar criptografia

Não criptografe senhas . Emvez disso,você deseja fazer o hash , usando um destes algoritmos de hash de senha:

Nunca use uma função de hash de uso geral (MD5, SHA256) para armazenamento de senha.

Não criptografe parâmetros de URL . É a ferramenta errada para o trabalho.

Exemplo de criptografia de seqüência de caracteres PHP com Libsodium

Se você estiver no PHP <7.2 ou não tiver o libsodium instalado, poderá usar o sódio_compat para obter o mesmo resultado (embora mais lento).

<?php
declare(strict_types=1);

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 * @throws RangeException
 */
function safeEncrypt(string $message, string $key): string
{
    if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
        throw new RangeException('Key is not the correct size (must be 32 bytes).');
    }
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

    $cipher = base64_encode(
        $nonce.
        sodium_crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
    sodium_memzero($message);
    sodium_memzero($key);
    return $cipher;
}

/**
 * Decrypt a message
 * 
 * @param string $encrypted - message encrypted with safeEncrypt()
 * @param string $key - encryption key
 * @return string
 * @throws Exception
 */
function safeDecrypt(string $encrypted, string $key): string
{   
    $decoded = base64_decode($encrypted);
    $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    $plain = sodium_crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
    if (!is_string($plain)) {
        throw new Exception('Invalid MAC');
    }
    sodium_memzero($ciphertext);
    sodium_memzero($key);
    return $plain;
}

Em seguida, para testá-lo:

<?php
// This refers to the previous code block.
require "safeCrypto.php"; 

// Do this once then store it somehow:
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
$message = 'We are all living in a yellow submarine';

$ciphertext = safeEncrypt($message, $key);
$plaintext = safeDecrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Halita - Libsodium Tornado Mais Fácil

Um dos projetos em que estou trabalhando é uma biblioteca de criptografia chamada Halite , que visa tornar o libsodium mais fácil e mais intuitivo.

<?php
use \ParagonIE\Halite\KeyFactory;
use \ParagonIE\Halite\Symmetric\Crypto as SymmetricCrypto;

// Generate a new random symmetric-key encryption key. You're going to want to store this:
$key = new KeyFactory::generateEncryptionKey();
// To save your encryption key:
KeyFactory::save($key, '/path/to/secret.key');
// To load it again:
$loadedkey = KeyFactory::loadEncryptionKey('/path/to/secret.key');

$message = 'We are all living in a yellow submarine';
$ciphertext = SymmetricCrypto::encrypt($message, $key);
$plaintext = SymmetricCrypto::decrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Toda a criptografia subjacente é manipulada pelo libsodium.

Exemplo com defuse / php-encryption

<?php
/**
 * This requires https://github.com/defuse/php-encryption
 * php composer.phar require defuse/php-encryption
 */

use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;

require "vendor/autoload.php";

// Do this once then store it somehow:
$key = Key::createNewRandomKey();

$message = 'We are all living in a yellow submarine';

$ciphertext = Crypto::encrypt($message, $key);
$plaintext = Crypto::decrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Nota : Crypto::encrypt()retorna a saída codificada em hexadecimal.

Gerenciamento de chave de criptografia

Se você estiver tentado a usar uma "senha", pare agora. Você precisa de uma chave de criptografia aleatória de 128 bits, não de uma senha memorável humana.

Você pode armazenar uma chave de criptografia para uso a longo prazo, como:

$storeMe = bin2hex($key);

E, sob demanda, você pode recuperá-lo da seguinte forma:

$key = hex2bin($storeMe);

Eu fortemente recomendo apenas armazenar uma chave gerada aleatoriamente para uso a longo prazo em vez de qualquer tipo de senha como a chave (ou para derivar a chave).

Se você estiver usando a biblioteca do Defuse:

"Mas eu realmente quero usar uma senha."

É uma má ideia, mas tudo bem, eis como fazê-lo com segurança.

Primeiro, gere uma chave aleatória e armazene-a em uma constante.

/**
 * Replace this with your own salt! 
 * Use bin2hex() then add \x before every 2 hex characters, like so:
 */
define('MY_PBKDF2_SALT', "\x2d\xb7\x68\x1a\x28\x15\xbe\x06\x33\xa0\x7e\x0e\x8f\x79\xd5\xdf");

Observe que você está adicionando trabalho extra e pode usar essa constante como chave e poupar muita dor de cabeça!

Em seguida, use PBKDF2 (assim) para obter uma chave de criptografia adequada da sua senha, em vez de criptografá-la diretamente.

/**
 * Get an AES key from a static password and a secret salt
 * 
 * @param string $password Your weak password here
 * @param int $keysize Number of bytes in encryption key
 */
function getKeyFromPassword($password, $keysize = 16)
{
    return hash_pbkdf2(
        'sha256',
        $password,
        MY_PBKDF2_SALT,
        100000, // Number of iterations
        $keysize,
        true
    );
}

Não use apenas uma senha de 16 caracteres. Sua chave de criptografia será comicamente quebrada.

Scott Arciszewski
fonte
3
Não criptografe senhas , faça hash com elas password_hash()e verifique com elas password_verify().
Scott Arciszewski
2
"Nunca comprima nada." Você quer dizer HTTP, spdy e outros protocolos? Antes do TLS? Conselho Absolutista muito?
Tiberiu-Ionuț Stan
1
@ScottArciszewski Eu gosto do seu comentário sobre a chave "// Faça isso uma vez e guarde-o de alguma forma:" .. de alguma forma, lol :)) bem, que tal armazenar essa 'chave' (que é objeto) como uma string simples, codificada? Eu preciso da chave em si, como uma string. Posso obtê-lo deste objeto de alguma forma? Graças
Andrew
2
Thx, eu tinha apenas que modificar uma linha para fazer seus exemplos de sódio funcionarem:function getKeyFromPassword($password, $keysize = \Sodium\CRYPTO_SECRETBOX_KEYBYTES)
Alexey Ozerov
1
Uau! +1 por mencionar não criptografar parâmetros de URL. Gostei muito do artigo que você fornece: paragonie.com/blog/2015/09/…
Lynnell Emmanuel Neri 28/09/18
73

Estou atrasado para a festa, mas, ao procurar a maneira correta de fazê-lo, encontrei esta página como uma das principais pesquisas do Google, então gostaria de compartilhar minha opinião sobre o problema, que considero ser atualizado no momento da redação deste post (início de 2017). A partir do PHP 7.1.0, o mcrypt_decrypte mcrypt_encryptserá descontinuado, portanto, a construção de código à prova de futuro deve usar o openssl_encrypt e o openssl_decrypt

Você pode fazer algo como:

$string_to_encrypt="Test";
$password="password";
$encrypted_string=openssl_encrypt($string_to_encrypt,"AES-128-ECB",$password);
$decrypted_string=openssl_decrypt($encrypted_string,"AES-128-ECB",$password);

Importante : usa o modo ECB , que não é seguro. Se você deseja uma solução simples sem fazer um curso intensivo em engenharia de criptografia, não escreva você mesmo, basta usar uma biblioteca.

Você também pode usar outros métodos de picador, dependendo da sua necessidade de segurança. Para descobrir os métodos disponíveis do picador, consulte a função openssl_get_cipher_methods .

Emil Borconi
fonte
10
Obrigado, estou surpreso que esta resposta simples e clara não seja mais votada. Prefiro não ler uma discussão de 10 páginas sobre o assunto como a resposta principal quando tudo o que quero é criptografar / descriptografar uma sequência simples.
laurent
4
Esta não é uma resposta segura. O modo BCE não deve ser usado. Se você deseja uma "resposta simples e clara", basta usar uma biblioteca .
22926 Scott Scallisz
2
@ScottArciszewski, sim, admito que falei rápido demais enquanto procurava por um código simples. Desde então, adicionei um IV e usei o CBC no meu próprio código, o que é bom o suficiente para o meu uso.
laurent
Leia isso e reconsidere . Com o modo CBC, um invasor pode alterar completamente a mensagem. Se a mensagem for um arquivo, um invasor poderá inverter os bits e ativar o calc.exe. Os riscos de criptografia não autenticada são graves.
22417 Scott Scallisz
7
Tudo depende do caso de uso! Há casos em que isso é perfeitamente Fino. Por exemplo, eu quero passar um parâmetro GET de uma página para outra, digamos, prod_id=123mas não quero tornar o 123 legível para todos, no entanto, mesmo que eles possam lê-lo, não será um problema. Um invasor capaz de substituir o 123 por um valor personalizado não causará nenhum dano, ele só poderá obter detalhes de qualquer outro produto, mas Joe Average User não terá idéia de como obter detalhes para produto 124, por exemplo. Para um cenário como esse, é uma solução perfeita, para segurança, é impossível!
Emil Borconi
43

O que não fazer

AVISO:
Esta resposta usa o BCE . O BCE não é um modo de criptografia, é apenas um componente básico. O uso do BCE, conforme demonstrado nesta resposta, na verdade não criptografa a string com segurança. Não use o BCE no seu código. Veja a resposta de Scott para uma boa solução.

Eu entendi. Na verdade, eu encontrei alguma resposta no google e apenas modifiquei algo. O resultado é completamente inseguro.

<?php
define("ENCRYPTION_KEY", "!@#$%^&*");
$string = "This is the original data string!";

echo $encrypted = encrypt($string, ENCRYPTION_KEY);
echo "<br />";
echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY);

/**
 * Returns an encrypted & utf8-encoded
 */
function encrypt($pure_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
    return $encrypted_string;
}

/**
 * Returns decrypted original string
 */
function decrypt($encrypted_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);
    return $decrypted_string;
}
?>
夏 期 劇場
fonte
8
Você pode usar o "MCRYPT_MODE_CBC" em vez de "MCRYPT_MODE_ECB" para garantir mais segurança.
Parixit 17/08/13
10
Ramesh, isso é porque você está recebendo os dados criptografados brutos. Você pode obter uma versão melhor dos dados criptografados usando base64, desta forma: base64_encode(encrypt($string))- Para descriptografá-lo:decrypt(base64_decode($encrypted))
mendezcode
82
AVISO: isso é inseguro . O modo ECB não deve ser usado para seqüências de caracteres, o BCE não usa um IV, isso não é autenticado, usa uma cifra antiga (Blowfish) em vez do AES, a chave não é binária etc. etc. A comunidade SO realmente deve parar de votar novamente na criptografia / descriptografia que apenas "funciona" e inicia a votação de respostas que são conhecidas por serem seguras. Se você não sabe ao certo, não vote.
Maarten Bodewes
3
Eu meio que já fiz isso mcrypt_encryptsubstituindo o código de exemplo : php.net/manual/en/function.mcrypt-encrypt.php . Observe que, analisando-o agora, provavelmente deve haver um rtrimcaractere for "\0"no final.
Maarten Bodewes
4
A resposta correta é usar algo como defuse / php-encryption em vez de escrever seu próprio código mcrypt.
Scott Arciszewski
18

Para framework Laravel

Se você estiver usando a estrutura do Laravel, é mais fácil criptografar e descriptografar com funções internas.

$string = 'Some text to be encrypted';
$encrypted = \Illuminate\Support\Facades\Crypt::encrypt($string);
$decrypted_string = \Illuminate\Support\Facades\Crypt::decrypt($encrypted);

var_dump($string);
var_dump($encrypted);
var_dump($decrypted_string);

Nota: Certifique-se de definir uma sequência aleatória de 16, 24 ou 32 caracteres na opção-chave do arquivo config / app.php. Caso contrário, os valores criptografados não serão seguros.

Somnath Muluk
fonte
1
Claro, pode ser fácil de usar. Mas é seguro? Como ele resolve os problemas no stackoverflow.com/a/30159120/781723 ? Ele usa criptografia autenticada? Evita vulnerabilidades de canal lateral e garante verificações de igualdade em tempo constante? Ele usa uma chave verdadeiramente aleatória em vez de uma senha / senha? Utiliza um modo de operação adequado? Isso gera IV aleatórios corretamente?
DW
10

Atualizada

Versão pronta para PHP 7. Ele usa a função openssl_encrypt da PHP OpenSSL Library .

class Openssl_EncryptDecrypt {
    function encrypt ($pure_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext_raw = openssl_encrypt($pure_string, $cipher, $encryption_key, $options, $iv);
        $hmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        return $iv.$hmac.$ciphertext_raw;
    }
    function decrypt ($encrypted_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = substr($encrypted_string, 0, $ivlen);
        $hmac = substr($encrypted_string, $ivlen, $sha2len);
        $ciphertext_raw = substr($encrypted_string, $ivlen+$sha2len);
        $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $encryption_key, $options, $iv);
        $calcmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        if(function_exists('hash_equals')) {
            if (hash_equals($hmac, $calcmac)) return $original_plaintext;
        } else {
            if ($this->hash_equals_custom($hmac, $calcmac)) return $original_plaintext;
        }
    }
    /**
     * (Optional)
     * hash_equals() function polyfilling.
     * PHP 5.6+ timing attack safe comparison
     */
    function hash_equals_custom($knownString, $userString) {
        if (function_exists('mb_strlen')) {
            $kLen = mb_strlen($knownString, '8bit');
            $uLen = mb_strlen($userString, '8bit');
        } else {
            $kLen = strlen($knownString);
            $uLen = strlen($userString);
        }
        if ($kLen !== $uLen) {
            return false;
        }
        $result = 0;
        for ($i = 0; $i < $kLen; $i++) {
            $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
        }
        return 0 === $result;
    }
}

define('ENCRYPTION_KEY', '__^%&Q@$&*!@#$%^&*^__');
$string = "This is the original string!";

$OpensslEncryption = new Openssl_EncryptDecrypt;
$encrypted = $OpensslEncryption->encrypt($string, ENCRYPTION_KEY);
$decrypted = $OpensslEncryption->decrypt($encrypted, ENCRYPTION_KEY);
夏 期 劇場
fonte
1
Esta é a versão melhor e muito mais segura. Obrigado, funciona como esperado também.
1
como você cria e onde mantém a chave de criptografia?
user2800464 12/04
7

Nota histórica: Isso foi escrito na época do PHP4. Isso é o que chamamos de "código herdado" agora.

Eu deixei essa resposta para fins históricos - mas alguns dos métodos agora estão obsoletos, o método de criptografia DES não é uma prática recomendada etc.

Não atualizei este código por dois motivos: 1) Não trabalho mais com métodos de criptografia manualmente no PHP e 2) esse código ainda serve ao objetivo a que se destinava: demonstrar o conceito simplista e mínimo de como a criptografia pode funcionar em PHP.

Se você encontrar um tipo de fonte similarmente simplista, "criptografia PHP para manequins", que pode iniciar as pessoas em 10 a 20 linhas de código ou menos, informe-me nos comentários.

Além disso, aproveite este episódio clássico da resposta de criptografia minimalista do PHP4 do início da era.


Idealmente, você tem - ou pode obter - acesso à biblioteca PHP mcrypt, pois é certamente uma variedade de tarefas popular e muito útil. Aqui está um resumo dos diferentes tipos de criptografia e algum código de exemplo: Técnicas de criptografia no PHP

//Listing 3: Encrypting Data Using the mcrypt_ecb Function 

<?php 
echo("<h3> Symmetric Encryption </h3>"); 
$key_value = "KEYVALUE"; 
$plain_text = "PLAINTEXT"; 
$encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT); 
echo ("<p><b> Text after encryption : </b>"); 
echo ( $encrypted_text ); 
$decrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $encrypted_text, MCRYPT_DECRYPT); 
echo ("<p><b> Text after decryption : </b>"); 
echo ( $decrypted_text ); 
?> 

Alguns avisos:

1) Nunca use criptografia reversível ou "simétrica" ​​quando houver um hash unidirecional.

2) Se os dados forem realmente confidenciais, como cartão de crédito ou números de previdência social, pare; você precisa de mais do que qualquer parte do código fornecer, mas precisa de uma biblioteca de criptografia projetada para esse fim e de uma quantidade significativa de tempo para pesquisar os métodos necessários. Além disso, a criptografia de software é provavelmente <10% da segurança de dados confidenciais. É como reconectar uma usina nuclear - aceite que a tarefa é perigosa e difícil e além do seu conhecimento, se for o caso. As sanções financeiras podem ser imensas, por isso é melhor usar um serviço e enviar responsabilidade a eles.

3) Qualquer tipo de criptografia facilmente implementável, conforme listado aqui, pode proteger razoavelmente informações levemente importantes que você deseja evitar de olhares indiscretos ou limitar a exposição em caso de vazamento acidental / intencional. Mas, vendo como a chave é armazenada em texto sem formatação no servidor da Web, se eles podem obter os dados, podem obter a chave de descriptografia.

Seja como for, divirta-se :)

BrianH
fonte
9
Eww, DES. Onde está o AES?
Patashu 17/05
2
Obrigado! Mas alguns problemas. Estou recebendo M�������f=�_=caracteres estranhos como o criptografado. Não consigo obter caracteres simples? Como: 2a2ffa8f13220befbe30819047e23b2c. Além disso, não posso alterar o COMPRIMENTO de $key_value(fixo em 8 ???) e o COMPRIMENTO de saída $encrypted_text? (que não pode ser 32 ou 64 de comprimento ou o que mais ??)
夏期劇場
3
@ 夏 期 劇場 O resultado da criptografia são dados binários. Se você precisar que seja legível por humanos, use a codificação base64 ou hexadecimal. "Não posso alterar o tamanho do valor da chave?" Algoritmos de criptografia simétrica diferentes têm requisitos diferentes para o valor da chave. 'e o COMPRIMENTO da saída ...' O comprimento do texto criptografado deve ser pelo menos o tamanho do texto original, ou então não há informações suficientes para recriar o texto original. (Esta é uma aplicação do princípio Pigeonhole.) BTW, você deve usar AES em vez de DES. O DES é facilmente quebrável e não é mais seguro.
Patashu 17/05
8
mcrypt_ecb foi DEPRECADO a partir do PHP 5.5.0 Confiar nessa função é altamente desencorajado. php.net/manual/en/function.mcrypt-ecb.php
Hafez Divandari
1
@BrianDHall A razão pela qual isso ainda recebe votos negativos é porque o modo BCE não é seguro (use CBC, CTR, GCM ou Poly1305), o DES é fraco (você deseja o AES MCRYPT_RIJNDAEL_128) e os textos cifrados devem ser autenticados ( hash_hmac(), verificados com hash_equals()).
Scott Arciszewski
7

Se você não quiser usar a biblioteca (o que deveria), use algo como isto (PHP 7):

function sign($message, $key) {
    return hash_hmac('sha256', $message, $key) . $message;
}

function verify($bundle, $key) {
    return hash_equals(
      hash_hmac('sha256', mb_substr($bundle, 64, null, '8bit'), $key),
      mb_substr($bundle, 0, 64, '8bit')
    );
}

function getKey($password, $keysize = 16) {
    return hash_pbkdf2('sha256',$password,'some_token',100000,$keysize,true);
}

function encrypt($message, $password) {
    $iv = random_bytes(16);
    $key = getKey($password);
    $result = sign(openssl_encrypt($message,'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv), $key);
    return bin2hex($iv).bin2hex($result);
}

function decrypt($hash, $password) {
    $iv = hex2bin(substr($hash, 0, 32));
    $data = hex2bin(substr($hash, 32));
    $key = getKey($password);
    if (!verify($data, $key)) {
      return null;
    }
    return openssl_decrypt(mb_substr($data, 64, null, '8bit'),'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv);
}

$string_to_encrypt='John Smith';
$password='password';
$encrypted_string=encrypt($string_to_encrypt, $password);
$decrypted_string=decrypt($encrypted_string, $password);
Ascon
fonte
Isso pode ser um substituto para stackoverflow.com/a/16606352/126833 ? Eu uso o primeiro até que meu host atualize para o PHP 7.2.
Anjanesh
@anjanesh você não será capaz de descriptografar os dados antigos com este (diferentes algoritmos + este também verificações de assinatura)
Ascon
2
No seu caso, provavelmente isso deve fazer:define("ENCRYPTION_KEY", "123456*"); $string = "This is the original data string!"; $encrypted = openssl_encrypt($string, 'BF-ECB', ENCRYPTION_KEY); $decrypted = openssl_decrypt($encrypted,'BF-ECB',ENCRYPTION_KEY);
Ascon
Isso é super!
Anjanesh
2

Estes são métodos compactos para criptografar / descriptografar seqüências de caracteres com PHP usando o AES256 CBC :

function encryptString($plaintext, $password, $encoding = null) {
    $iv = openssl_random_pseudo_bytes(16);
    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, $iv);
    $hmac = hash_hmac('sha256', $ciphertext.$iv, hash('sha256', $password, true), true);
    return $encoding == "hex" ? bin2hex($iv.$hmac.$ciphertext) : ($encoding == "base64" ? base64_encode($iv.$hmac.$ciphertext) : $iv.$hmac.$ciphertext);
}

function decryptString($ciphertext, $password, $encoding = null) {
    $ciphertext = $encoding == "hex" ? hex2bin($ciphertext) : ($encoding == "base64" ? base64_decode($ciphertext) : $ciphertext);
    if (!hash_equals(hash_hmac('sha256', substr($ciphertext, 48).substr($ciphertext, 0, 16), hash('sha256', $password, true), true), substr($ciphertext, 16, 32))) return null;
    return openssl_decrypt(substr($ciphertext, 48), "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, substr($ciphertext, 0, 16));
}

Uso:

$enc = encryptString("mysecretText", "myPassword");
$dec = decryptString($enc, "myPassword");
Marco Concas
fonte
0

Abaixo do código, trabalho em php para todas as strings com caracteres especiais

   // Encrypt text --

    $token = "9611222007552";

      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);  
      $enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));  
      $crypted_token = openssl_encrypt($token, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
    echo    $crypted_token;
    //unset($token, $cipher_method, $enc_key, $enc_iv);

    // Decrypt text  -- 

    list($crypted_token, $enc_iv) = explode("::", $crypted_token);  
      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);
      $token = openssl_decrypt($crypted_token, $cipher_method, $enc_key, 0, hex2bin($enc_iv));
    echo   $token;
    //unset($crypted_token, $cipher_method, $enc_key, $enc_iv);
Javed
fonte