Skip to content

Instantly share code, notes, and snippets.

@richjenks
Last active June 14, 2023 14:52
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save richjenks/646ddd6e4a4d67290ae3 to your computer and use it in GitHub Desktop.
Save richjenks/646ddd6e4a4d67290ae3 to your computer and use it in GitHub Desktop.
Simple PHP Encryption & Decryption
<?php
/**
* Simple PHP Encryption functions
*
* Attempts to be as secure as possible given:
*
* - Key can be any string
* - No knowledge of encryption is required
* - Only key and raw/encrypted string is needed at each end
* - Metadata can be anything (string, array, etc.)
*
* If possible, always prefer a library like https://github.com/defuse/php-encryption
* and only use these functions if that isn't possible
*
* Adapted from http://stackoverflow.com/a/30239440/1562799
*/
/**
* Encrypts a string
*
* @param string $key Encryption key, also required for decryption
* @param string $raw Raw string to be encrypted
* @param mixed $meta Associated data that must be provided during decryption
*
* @return string Raw data encrypted with key
*/
function encrypt( $key, $plaintext, $meta = '' ) {
// Generate valid key
$key = hash_pbkdf2( 'sha256', $key, '', 10000, 0, true );
// Serialize metadata
$meta = serialize($meta);
// Derive two subkeys from the original key
$mac_key = hash_hmac( 'sha256', 'mac', $key, true );
$enc_key = hash_hmac( 'sha256', 'enc', $key, true );
$enc_key = substr( $enc_key, 0, 32 );
// Derive a "synthetic IV" from the nonce, plaintext and metadata
$temp = $nonce = ( 16 > 0 ? mcrypt_create_iv( 16 ) : "" );
$temp .= hash_hmac( 'sha256', $plaintext, $mac_key, true );
$temp .= hash_hmac( 'sha256', $meta, $mac_key, true );
$mac = hash_hmac( 'sha256', $temp, $mac_key, true );
$siv = substr( $mac, 0, 16 );
// Encrypt the message
$enc = mcrypt_encrypt( 'rijndael-128', $enc_key, $plaintext, 'ctr', $siv );
return base64_encode( $siv . $nonce . $enc );
}
/**
* Decrypts an encrypted string
*
* @param string $key Encryption key, also used during encryption
* @param string $encrypted Encrypted string to be decrypted
* @param mixed $meta Associated data that must be the same as when encrypted
*
* @return string Decrypted string or `null` if key/meta has been tampered with
*/
function decrypt( $key, $ciphertext, $meta = '' ) {
// Generate valid key
$key = hash_pbkdf2( 'sha256', $key, '', 10000, 0, true );
// Serialize metadata
$meta = serialize($meta);
// Derive two subkeys from the original key
$mac_key = hash_hmac( 'sha256', 'mac', $key, true );
$enc_key = hash_hmac( 'sha256', 'enc', $key, true );
$enc_key = substr( $enc_key, 0, 32 );
// Unpack MAC, nonce and encrypted message from the ciphertext
$enc = base64_decode( $ciphertext );
$siv = substr( $enc, 0, 16 );
$nonce = substr( $enc, 16, 16 );
$enc = substr( $enc, 16 + 16 );
// Decrypt message
$plaintext = mcrypt_decrypt( 'rijndael-128', $enc_key, $enc, 'ctr', $siv );
// Verify MAC, return null if message is invalid
$temp = $nonce;
$temp .= hash_hmac( 'sha256', $plaintext, $mac_key, true );
$temp .= hash_hmac( 'sha256', $meta, $mac_key, true );
$mac = hash_hmac( 'sha256', $temp, $mac_key, true );
if ( $siv !== substr( $mac, 0, 16 ) ) return null;
return $plaintext;
}
/**
* Encrypts a string
*
* Do not use this function, it is only here for historical reference
*
* @param string $key Encryption key, also required for decryption
* @param string $raw Raw string to be encrypted
*
* @return string Raw data encrypted with key
*/
// function encrypt($key, $raw) {
// return base64_encode(mcrypt_encrypt(
// MCRYPT_RIJNDAEL_256,
// md5($key),
// $raw,
// MCRYPT_MODE_CBC,
// md5(md5($key))
// ));
// }
/**
* Decrypts an encrypted string
*
* Do not use this function, it is only here for historical reference
*
* @param string $key Encryption key, also used during encryption
* @param string $encrypted Encrypted string to be decrypted
*
* @return string Decrypted string or `null` if key/meta has been tampered with
*/
// function decrypt($key, $encrypted) {
// return rtrim(
// mcrypt_decrypt(
// MCRYPT_RIJNDAEL_256,
// md5($key),
// base64_decode($encrypted),
// MCRYPT_MODE_CBC,
// md5(md5($key))
// )
// );
// }
<?php
require 'encrypt-decrypt.php';
$key = 'letmein';
$raw = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.';
$meta = [ 'name' => 'Rich', 'email' => 'rich@richjenks.com' ];
$encrypted = encrypt($key, $raw, $meta);
$decrypted = decrypt($key, $encrypted, $meta);
echo 'KEY:';
var_dump($key);
echo 'RAW:';
var_dump($raw);
echo 'META:';
var_dump($meta);
echo 'ENCRYPTED:';
var_dump($encrypted);
echo 'DENCRYPTED:';
var_dump($decrypted);
@ihrifat2
Copy link

ihrifat2 commented Mar 9, 2019

Not working. it showing a fatal error "Fatal error: Uncaught Error: Call to undefined function mcrypt_create_iv()". because this function has been deprecated from PHP version 7.

@unix4you2
Copy link

Hi there!

For any person that could be looking for crypting info please don't use this method. You should use OpenSSL instead https://www.php.net/manual/es/book.openssl.php

Best regards.

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