security - How do you Encrypt and Decrypt a PHP String? -


what mean is:

original string + salt or key --> encrypted string encrypted string + salt or key --> decrypted (original string) 

maybe like:

"hello world!" + "abcd1234" --> encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, e.g) "2a2ffa8f13220befbe30819047e23b2c" --> decrypt "abcd1234" --> "hello world!" 
  • in php, how can this?

attempted use crypt_blowfish, didn't work me.

before further, seek understand the difference between encryption , authentication, , why want authenticated encryption rather encryption.

to implement authenticated encryption, want encrypt mac. the order of encryption , authentication important! 1 of existing answers question made mistake; many cryptography libraries written in php.

you should avoid implementing own cryptography, , instead use secure library written , reviewed cryptography experts.

use libsodium if have pecl access (or sodium_compat if want libsodium without pecl); otherwise...
use defuse/php-encryption; don't roll own cryptography!

both of libraries linked above above make easy , painless implement authenticated encryption own libraries.

if still want write , deploy own cryptography library, against conventional wisdom of every cryptography expert on internet, these steps have take.

encryption:

  1. encrypt using aes in ctr mode. may use gcm (which removes need separate mac). additionally, chacha20 , salsa20 (provided libsodium) stream ciphers , not need special modes.
  2. unless chose gcm above, should authenticate ciphertext hmac-sha-256 (or, stream ciphers, poly1305 -- libsodium apis you). the mac should cover iv ciphertext!

decryption:

  1. unless poly1305 or gcm used, recalculate mac of ciphertext , compare mac sent using hash_equals(). if fails, abort.
  2. decrypt message.

other design considerations:

  1. do not compress ever. ciphertext not compressible; compressing plaintext before encryption can lead information leaks (e.g. crime , breach on tls).
  2. make sure use mb_strlen() , mb_substr(), using '8bit' character set mode prevent mbstring.func_overload issues.
  3. ivs should generating using csprng; if you're using mcrypt_create_iv(), do not use mcrypt_rand!
  4. unless you're using aead construct, always encrypt mac!
  5. bin2hex(), base64_encode(), etc. may leak information encryption keys via cache timing. avoid them if possible.

even if follow advice given here, lot can go wrong cryptography. always have cryptography expert review implementation. if not fortunate enough personal friends cryptography student @ local university, can try cryptography stack exchange forum advice.

if need professional analysis of implementation, can hire reputable team of security consultants review php cryptography code (disclosure: employer).

important: when not use encryption

don't encrypt passwords. want hash them instead, using 1 of these password-hashing algorithms:

never use general-purpose hash function (md5, sha256) password storage.

don't encrypt url parameters. it's wrong tool job.

php string encryption example libsodium

if not have libsodium installed, can use sodium_compat accomplish same result (albeit slower).

<?php // requires libsodium pecl extension  /**  * encrypt message  *   * @param string $message - message encrypt  * @param string $key - encryption key  * @return string  */ function safeencrypt($message, $key) {     $nonce = \sodium\randombytes_buf(         \sodium\crypto_secretbox_noncebytes     );      $cipher = base64_encode(         $nonce.         \sodium\crypto_secretbox(             $message,             $nonce,             $key         )     );     \sodium\memzero($message);     \sodium\memzero($key);     return $cipher; }  /**  * decrypt message  *   * @param string $encrypted - message encrypted 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');      $plain = \sodium\crypto_secretbox_open(         $ciphertext,         $nonce,         $key     );     \sodium\memzero($ciphertext);     \sodium\memzero($key);     return $plain; } 

then test out:

<?php // refers previous code block. require "safecrypto.php";   // once store somehow: $key = \sodium\randombytes_buf(     \sodium\crypto_secretbox_keybytes ); $message = 'we living in yellow submarine';  $ciphertext = safeencrypt($message, $key); $plaintext = safedecrypt($ciphertext, $key);  var_dump($ciphertext); var_dump($plaintext); 

halite - libsodium made easier

one of projects i've been working on encryption library called halite, aims make libsodium easier , more intuitive.

<?php use \paragonie\halite\keyfactory; use \paragonie\halite\symmetric\crypto symmetriccrypto;  // generate new random symmetric-key encryption key. you're going want store this: $key = new keyfactory::generateencryptionkey(); // save encryption key: keyfactory::save($key, '/path/to/secret.key'); // load again: $loadedkey = keyfactory::loadencryptionkey('/path/to/secret.key');  $message = 'we living in yellow submarine'; $ciphertext = symmetriccrypto::encrypt($message, $key); $plaintext = symmetriccrypto::decrypt($ciphertext, $key);  var_dump($ciphertext); var_dump($plaintext); 

all of underlying cryptography handled libsodium. obviously, means need pecl extension use halite.

example defuse/php-encryption

<?php /**  * requires https://github.com/defuse/php-encryption  * php composer.phar require defuse/php-encryption  *   * note v2.0.0 around corner , might need  * edited when it's released.  */  use \defuse\crypto\crypto;  require "vendor/autoload.php";  // once store somehow: $key = crypto::createnewrandomkey();  $message = 'we living in yellow submarine';  $ciphertext = crypto::encrypt($message, $key); $plaintext = crypto::decrypt($ciphertext, $key);  var_dump($ciphertext); var_dump($plaintext); 

note: crypto::encrypt() returns raw binary, may want use base64_encode() , base64_decode()for storing/transmitting ciphertexts prevent encoding bugs. in version 2, default hex-encoded output.

encryption key management

if you're tempted use "password", stop right now. need random 128-bit encryption key, not human memorable password.

you can store encryption key long-term use so:

$storeme = bin2hex($key); 

and, on demand, can retrieve so:

$key = hex2bin($storeme); 

i strongly recommend storing randomly generated key long-term use instead of sort of password key (or derive key).

"but really want use password."

that's bad idea, okay, here's how safely.

first, generate random key , store in constant.

/**  * replace own salt!   * use bin2hex() add \x before every 2 hex characters, so:  */ define('my_pbkdf2_salt', "\x2d\xb7\x68\x1a\x28\x15\xbe\x06\x33\xa0\x7e\x0e\x8f\x79\xd5\xdf"); 

note you're adding work , use constant key , save lot of heartache!

then use pbkdf2 (like so) derive suitable encryption key password rather encrypting password directly.

/**  * aes key static password , secret salt  *   * @param string $password 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     ); } 

don't use 16-character password. encryption key comically broken.


Comments

Popular posts from this blog

apache - PHP Soap issue while content length is larger -

asynchronous - Python asyncio task got bad yield -

javascript - Complete OpenIDConnect auth when requesting via Ajax -