Skip to content

Instantly share code, notes, and snippets.

@fosron
Created July 23, 2015 09:14
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save fosron/5c7f2c39e49755f83614 to your computer and use it in GitHub Desktop.
Save fosron/5c7f2c39e49755f83614 to your computer and use it in GitHub Desktop.
Modern method to encrypt/decrypt a string in PHP
<?php
/**
* Simple string encryption/decryption function.
* CHANGE $secret_key and $secret_iv !!!
**/
function stringEncryption($action, $string){
$output = false;
$encrypt_method = 'AES-256-CBC'; // Default
$secret_key = 'Some#Random_Key!'; // Change the key!
$secret_iv = '!IV@_$2'; // Change the init vector!
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
}
else if( $action == 'decrypt' ){
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
/**
* Example
*
**/
echo '<pre>';
$info = 'This is really secret!';
echo 'info = '.$info."\n";
$encrypted = stringEncryption('encrypt', $info);
echo 'encrypted = '.$encrypted."\n";
$decrypted = stringEncryption('decrypt', $encrypted);
echo 'decrypted = '.$decrypted."\n";
echo '</pre>';
?>
@paragonie-scott
Copy link

  $secret_key = 'Some#Random_Key!';               // Change the key!

You don't want a password, you want a string of 16, 24, or 32 random bytes. Since you specified AES-256, you want 32 bytes.

  $key = hash('sha256', $secret_key);

A single pass of SHA-256 is not a strong KDF. You want hash_pbkdf2() if you're going to use a password to generate a key.

  $secret_iv = '!IV@_$2';  // Change the init vector!

The IV should be randomly generated and stored with the ciphertext.

  // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
  $iv = substr(hash('sha256', $secret_iv), 0, 16);

AES-256-CBC expects 32 bytes for a key and 16 bytes for an IV. However, mb_substr($str, $start, $length, '8bit'); is the canonical way to count bytes in PHP due to mbstring.func_overload.

  if( $action == 'encrypt' ) {
      $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
      $output = base64_encode($output);
  }
  else if( $action == 'decrypt' ){
      $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
  }
  return $output;

Why are you using one function for two inverse operations?

You're encypting a string, but since you're not authenticating your message, this encryption is incredibly brittle. The static IV an weak KDF on $secret_key makes it even worse.

You might want to read our guide to authenticated encryption in PHP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment