Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP AES encrypt / decrypt

I found an example for en/decoding strings in PHP. At first it looks very good but it wont work :-(

Does anyone know what the problem is?

$Pass = "Passwort"; $Clear = "Klartext";  $crypted = fnEncrypt($Clear, $Pass); echo "Encrypted: ".$crypted."</br>";  $newClear = fnDecrypt($crypted, $Pass); echo "Decrypted: ".$newClear."</br>";  function fnEncrypt($sValue, $sSecretKey) {     return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sDecrypted, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); }  function fnDecrypt($sValue, $sSecretKey) {     return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sEncrypted), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); } 

The result is:

Encrypted: boKRNTYYNp7AiOvY1CidqsAn9wX4ufz/D9XrpjAOPk8=

Decrypted: —‚(ÑÁ ^ yË~F'¸®Ó–í œð2Á_B‰Â—

like image 555
Andreas Prang Avatar asked Aug 06 '10 10:08

Andreas Prang


People also ask

How do you use encrypt and decrypt in PHP?

In PHP, Encryption and Decryption of a string is possible using one of the Cryptography Extensions called OpenSSL function for encrypt and decrypt. openssl_encrypt() Function: The openssl_encrypt() function is used to encrypt the data. Parameters: $data: It holds the string or data which need to be encrypted.

Can PHP encrypt data?

PHP encryption is important to the privacy and safety of your data. In practical terms, PHP encryption uses algorithms (sometimes called hashing algorithms) to translate the “clear” data into encrypted text that requires very specific decryption processes to “decode” the data back to the clean version.


2 Answers

Please use an existing secure PHP encryption library

It's generally a bad idea to write your own cryptography unless you have experience breaking other peoples' cryptography implementations.

None of the examples here authenticate the ciphertext, which leaves them vulnerable to bit-rewriting attacks.

If you can install PECL extensions, libsodium is even better

<?php // PECL libsodium 0.2.1 and newer  /**  * Encrypt a message  *   * @param string $message - message to encrypt  * @param string $key - encryption key  * @return string  */ function safeEncrypt($message, $key) {     $nonce = \Sodium\randombytes_buf(         \Sodium\CRYPTO_SECRETBOX_NONCEBYTES     );      return base64_encode(         $nonce.         \Sodium\crypto_secretbox(             $message,             $nonce,             $key         )     ); }  /**  * Decrypt a message  *   * @param string $encrypted - message encrypted with safeEncrypt()  * @param string $key - encryption key  * @return string  */ function safeDecrypt($encrypted, $key) {        $decoded = base64_decode($encrypted);     $nonce = mb_substr($decoded, 0, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, '8bit');     $ciphertext = mb_substr($decoded, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');      return \Sodium\crypto_secretbox_open(         $ciphertext,         $nonce,         $key     ); }     

Then to test it out:

<?php // This refers to the previous code block. require "safeCrypto.php";   // Do this once then store it somehow: $key = \Sodium\randombytes_buf(\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); 

This can be used in any situation where you are passing data to the client (e.g. encrypted cookies for sessions without server-side storage, encrypted URL parameters, etc.) with a reasonably high degree of certainty that the end user cannot decipher or reliably tamper with it.

Since libsodium is cross-platform, this also makes it easier to communicate with PHP from, e.g. Java applets or native mobile apps.


Note: If you specifically need to add encrypted cookies powered by libsodium to your app, my employer Paragon Initiative Enterprises is developing a library called Halite that does all of this for you.

like image 103
Scott Arciszewski Avatar answered Sep 23 '22 10:09

Scott Arciszewski


If you don't want to use a heavy dependency for something solvable in 15 lines of code, use the built in OpenSSL functions. Most PHP installations come with OpenSSL, which provides fast, compatible and secure AES encryption in PHP. Well, it's secure as long as you're following the best practices.

The following code:

  • uses AES256 in CBC mode
  • is compatible with other AES implementations, but not mcrypt, since mcrypt uses PKCS#5 instead of PKCS#7.
  • generates a key from the provided password using SHA256
  • generates a hmac hash of the encrypted data for integrity check
  • generates a random IV for each message
  • prepends the IV (16 bytes) and the hash (32 bytes) to the ciphertext
  • should be pretty secure

IV is a public information and needs to be random for each message. The hash ensures that the data hasn't been tampered with.

function encrypt($plaintext, $password) {     $method = "AES-256-CBC";     $key = hash('sha256', $password, true);     $iv = openssl_random_pseudo_bytes(16);      $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);     $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);      return $iv . $hash . $ciphertext; }  function decrypt($ivHashCiphertext, $password) {     $method = "AES-256-CBC";     $iv = substr($ivHashCiphertext, 0, 16);     $hash = substr($ivHashCiphertext, 16, 32);     $ciphertext = substr($ivHashCiphertext, 48);     $key = hash('sha256', $password, true);      if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;      return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv); } 

Usage:

$encrypted = encrypt('Plaintext string.', 'password'); // this yields a binary string  echo decrypt($encrypted, 'password'); // decrypt($encrypted, 'wrong password') === null 

edit: Updated to use hash_equals and added IV to the hash.

like image 29
blade Avatar answered Sep 20 '22 10:09

blade