Skip to content

Instantly share code, notes, and snippets.

@joashp
Created September 4, 2015 15:59
Show Gist options
  • Save joashp/a1ae9cb30fa533f4ad94 to your computer and use it in GitHub Desktop.
Save joashp/a1ae9cb30fa533f4ad94 to your computer and use it in GitHub Desktop.
Simple PHP encrypt and decrypt using OpenSSL
<?php
/**
* simple method to encrypt or decrypt a plain text string
* initialization vector(IV) has to be the same when encrypting and decrypting
*
* @param string $action: can be 'encrypt' or 'decrypt'
* @param string $string: string to encrypt or decrypt
*
* @return string
*/
function encrypt_decrypt($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = 'This is my secret key';
$secret_iv = 'This is my secret iv';
// 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;
}
$plain_txt = "This is my plain text";
echo "Plain Text =" .$plain_txt. "\n";
$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = " .$encrypted_txt. "\n";
$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text =" .$decrypted_txt. "\n";
if ( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";
echo "\n";
?>
@crsland
Copy link

crsland commented Aug 7, 2017

Like this gist, I don't think you need line 26 though. openssl_encrypt will return a base64 encoded string with the given parameters

@cyth319
Copy link

cyth319 commented Sep 1, 2017

thank you thank you thank you thank you thank you

@sourovroy
Copy link

Thank you very much, It helps me

@kidx5452
Copy link

kidx5452 commented Oct 13, 2017

I'm using nodejs v6.
This is my code for decrypt by nodejs when using php to encrypt

PHP
$encrypt_method = "AES-256-CBC"; $secret_key = '6818f23eef19d38dad1d2729991f6368'; $secret_iv = '0ac35e3823616c810f86e526d1ed59e7'; $enc = 'a1pORHBTOEdaV1BsZTFXYUF6cXlsUGV4VVp4bUpJRHlzL2Jma0VMaGtmNVIzRUZ1VmNUbTZWVlo5cGczQUxiRmQvYXIzK0p0R1BkdnM0MU1PaU1qcmRkRmZXUW1PYjdQRHIwRDRhN2ZHRHZUWVllUktMQW1lQkNvamxnTlUwbEd5MmpsMXpORzhGS3JYY3hlRnJpL1pzQllhL28xVllYMGEwRUFwcG1uY1pHMW05cWVUd2ZpM3NaekxjNjE0aDhoZkVDRHc3cktOY3ZzNWtOeHJldXhnQjB3ekhXeGFQZElOek9MNkFjdDkrVWZQcFlYRW9KN0lvT2N2TmJXcXM0bw=='; $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); $output = openssl_decrypt(base64_decode($enc), $encrypt_method, $key, 0, $iv); echo $output;

Output: EAAEug8sk8GgBAC0XZCsp6KB1ZAaL2sSAuDEELVLc5tWZBJW2EQ0WmBCdZBAkimZAgCCIEeZB4lnwSGNk0v0SScThjBbWoMuVWJqUqgSAV75JK0kcYh24ZAqKvkEirzIEEVjgu2QqFdJxuWfDX5a58y5mgAP7BPFPgKEZBYmFVBHJZBbLT2Ye9GYaR
PHP can be decrypt.

NodeJS:
`var crypto = require('crypto');
var CryptoJS = require("crypto-js");
var key = '6818f23eef19d38dad1d2729991f6368';
var iv = '0ac35e3823616c810f86e526d1ed59e7';
var enc = 'M0dvV1hlK0cvT2JrWWJFMGlGN1gyZnJLK0YwWTRTQ2N2N0NxdnIvWnYySHB0VVI2NTZZczNmYlhQVFF5VXFhblQ3WGd4OTBWd01xdlFPT3dLcDdJVUhKeEgyTzREVUY4blMzeXg1Rk9sajg4NU9JbkVOamJoZ215clB4dXROS2daVElQendKenMzV0FwOEQveG93SS93d2hVckpzcTVLKzhDWmhXUEE0Z2dqVU1OK2k0ZVN5bGhIcmt5T1c2bzNxc1UybDdQdzRxUzU3ZG9BS2g5K2d3Q21FME93ZDM0dmRRakU0NWZTK0RRbCtxTXlmLzZPUytpeVBpQUJDYzNoWg==';
var parsed_iv = CryptoJS.SHA256(iv).toString().substring(0, 16);

function decrypt(k, i, v) {
v = new Buffer(v, 'base64');
var decipher = crypto.createDecipheriv('aes-256-cbc', k, i);
decipher.setAutoPadding(false);
var s = decipher.update(v, 'base64', 'utf8');
return Buffer.concat([s,decipher.final('utf8')]);
}
var dec = decrypt(key, parsed_iv, enc);
console.log(dec);
`
I try very much code by search google but it's return binary and i can't convert it into text.
Hope you can help me.
Thanks !

@itmalan
Copy link

itmalan commented Oct 13, 2017

It is really a nice post and clearly understandable.

I have an issue in openssl_encrypt(), please help me. I have to do AES-128-ECB with PKCS5 padding. How do I make PKCS5 in openssl_encrypt(). In few online posts it was mentioned openssl_encrypt will do PKCS5/7 padding by default if no option is mentioned.

Thanks in advance

@bladeSk
Copy link

bladeSk commented Oct 22, 2017

The IV should be generated for each encrypted message and transmitted with the message. Sending 2 or more messages with the same IV is a serious security flaw. You can use $iv = openssl_random_pseudo_bytes(16) to generate IVs. This shouldn't rely on insecure random number generators such as rand().

Furthermore, you should use actual bytes for key instead of a hex string. Hex string is significantly reducing the possible combinations. $key = hash('sha256', $password, true);

Edit: here's my full code, if you're interested https://stackoverflow.com/a/46872528/388994

@petermuller71
Copy link

The problem with open_ssl is that is cannot work with large strings. You get errors...
So you have to split a large string in smaller chuncks..

And as bladeSk mentionend: The IV should be generated for each encrypted message and transmitted with the message.

See working example at (written as static class):
https://gist.github.com/petermuller71/33616d55174d9725fc00a663d30194ba

@test8git
Copy link

test8git commented Jan 3, 2018

Thank u so much

@jbvazquez
Copy link

jbvazquez commented Jan 10, 2018

Hi is correct if use a secretkey generated with RSA 2048 and as secret_iv a public key?

@twicejr
Copy link

twicejr commented Jan 29, 2018

You should always use a random Initialization Vector if you want to protect against replaying attacks. (although the probability of it happening is low)
You can just append or prepend the IV to the output and use it in your decrypt function, it may be exposed publically.

@budhapirthi
Copy link

thanks so much for sharing

@Alemalakra
Copy link

Nice share fam.

@czubehead
Copy link

This is dangerous! IV MUST be random, that is the whole purpose of it. You have just disabled one of the cipher's key mechanisms, well done.

@petemolinero
Copy link

@czubehead If it's random, how would you decrypt? How would you modify the code for a more secure encrypt/decrypt?

@spybart
Copy link

spybart commented Jun 10, 2018

@petemolinero read the reply by @twicejr and @bladeSk

@Rubinum
Copy link

Rubinum commented Jul 16, 2018

This function does two things instead of one and yes functions should do one thing. The name of the function is aweful too! Please don't write such code in that way if you copy that into your projects.

@IwonGunawan
Copy link

thank you so much for sharing.
this code help me, very simple and easy to use.

@jagdeepmalhi
Copy link

Thanks for sharing.

@legendblogs
Copy link

Mcrypt is a replacement for the popular Unix crypt command. the crypt was a file encryption tool that used an algorithm very close to the World War II Enigma cipher. Mcrypt provides the same functionality but uses several modern algorithms such as AES.

class MCrypt {

private $iv = 'abcdef9876541720';
private $key = '1720456789fedcba';

function __construct() {
    
}

/**
 * @param string $str
 * @param bool $isBinary whether to encrypt as binary or not. Default is: false
 * @return string Encrypted data
 */
function encrypt($str, $isBinary = false) {
    $iv = $this->iv;
    $str = $isBinary ? $str : utf8_decode($str);
    $td = mcrypt_module_open('rijndael-128', ' ', 'cbc', $iv);
    mcrypt_generic_init($td, $this->key, $iv);
    $encrypted = mcrypt_generic($td, $str);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $isBinary ? $encrypted : bin2hex($encrypted);
}

/**
 * @param string $code
 * @param bool $isBinary whether to decrypt as binary or not. Default is: false
 * @return string Decrypted data
 */
function decrypt($code, $isBinary = false) {
    $code = $isBinary ? $code : $this->hex2bin($code);
    $iv = $this->iv;
    $td = mcrypt_module_open('rijndael-128', ' ', 'cbc', $iv);
    mcrypt_generic_init($td, $this->key, $iv);
    $decrypted = mdecrypt_generic($td, $code);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $isBinary ? trim($decrypted) : utf8_encode(trim($decrypted));
}

protected function hex2bin($hexdata) {
    $bindata = '';
    for ($i = 0; $i < strlen($hexdata); $i += 2) {
        $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
    }
    return $bindata;
}

}

function encryptkey($key) {
$mcrypt = new MCrypt();
$encrypted = $mcrypt->encrypt($key);
return $encrypted;
}

function decryptkey($key) {
$mcrypt = new MCrypt();
$decrypted = $mcrypt->decrypt($key);
return $decrypted;
}

$value = "Legend Blogs";

echo $value.'
';
echo "Encrypt: ". encryptkey($value).'
';
echo "Decrypt: ". decryptkey(encryptkey($value)).'
';

Complete example at here How do you Encrypt and Decrypt a PHP String

@tonnas
Copy link

tonnas commented Mar 21, 2019

Thanks Man !

@josegoyo
Copy link

josegoyo commented May 15, 2019

How can I decrypt this in java ?

Copy link

ghost commented Jul 22, 2019

Thank you so much, but I have some questions :

  1. Is it safe to use that code in my website when every one know it?
  2. What's the maximum length of the $secret_key and the $secret_iv?
  3. What's the best way to hide that code from everyone?

-Adel Sbeh

@AkshayKhandarkar
Copy link

How to add cs5 padding with the encryption?? please, I need to know urgently.

@Josloader3
Copy link

great code, thanks a lot

@neutronixx
Copy link

Hello thanks for the code, works well, and works with short text strings but how I can encrypt text longer?

@BySkilz0
Copy link

Hello from 2021,
Helped me ;)

@LeoDaGuy
Copy link

Helped me 👍

@aacassandra
Copy link

How can I decrypt this in java ?

simple, you must move to php. haha. just kidding

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