Skip to content

Instantly share code, notes, and snippets.

@Tiriel
Last active June 21, 2024 07:53
Show Gist options
  • Save Tiriel/bff8b06cb3359bba5f9e9ba1f9fc52c0 to your computer and use it in GitHub Desktop.
Save Tiriel/bff8b06cb3359bba5f9e9ba1f9fc52c0 to your computer and use it in GitHub Desktop.
Symetric encryption/decryption for PHP and NodeJS communication
'use strict';
const crypto = require('crypto');
const AES_METHOD = 'aes-256-cbc';
const IV_LENGTH = 16; // For AES, this is always 16, checked with php
const password = 'lbwyBzfgzUIvXZFShJuikaWvLJhIVq36'; // Must be 256 bytes (32 characters)
function encrypt(text, password) {
if (process.versions.openssl <= '1.0.1f') {
throw new Error('OpenSSL Version too old, vulnerability to Heartbleed')
}
let iv = crypto.randomBytes(IV_LENGTH);
let cipher = crypto.createCipheriv(AES_METHOD, new Buffer(password), iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + ':' + encrypted.toString('hex');
}
function decrypt(text) {
let textParts = text.split(':');
let iv = new Buffer(textParts.shift(), 'hex');
let encryptedText = new Buffer(textParts.join(':'), 'hex');
let decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer($password), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
<?php
define('AES_METHOD', 'aes-256-cbc');
$password = 'lbwyBzfgzUIvXZFShJuikaWvLJhIVq36';
function encrypt($message, $password)
{
if (OPENSSL_VERSION_NUMBER <= 268443727) {
throw new RuntimeException('OpenSSL Version too old, vulnerability to Heartbleed');
}
$iv_size = openssl_cipher_iv_length(AES_METHOD);
$iv = openssl_random_pseudo_bytes($iv_size);
$ciphertext = openssl_encrypt($message, AES_METHOD, $password, OPENSSL_RAW_DATA, $iv);
$ciphertext_hex = bin2hex($ciphertext);
$iv_hex = bin2hex($iv);
return "$iv_hex:$ciphertext_hex";
}
function decrypt($ciphered, $password) {
$iv_size = openssl_cipher_iv_length(AES_METHOD);
$data = explode(":", $ciphered);
$iv = hex2bin($data[0]);
$ciphertext = hex2bin($data[1]);
return openssl_decrypt($ciphertext, AES_METHOD, $password, OPENSSL_RAW_DATA, $iv);
}
@lomelisan
Copy link

lomelisan commented Aug 6, 2018

Thank you so much guys. Works perfect.

Just had to change line 28 of encryption.js from
let decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);

to
let decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer($password), iv);

@yjradeh
Copy link

yjradeh commented Oct 24, 2019

What the purpose of this line
if (process.versions.openssl <= '1.0.1f') {

shouldn't it be the opposite? like if (process.versions.openssl >= '1.0.1f') {

@Moses-Bassey
Copy link

Moses-Bassey commented May 8, 2020

What the purpose of this line
if (process.versions.openssl <= '1.0.1f') {

shouldn't it be the opposite? like if (process.versions.openssl >= '1.0.1f') {

I think the code snippets work with version 1.0.1f down

@Tiriel
Copy link
Author

Tiriel commented May 8, 2020

Actually, it's "throw an error if version is inferior or equal to 1.0.1f
if (process.versions.openssl <= '1.0.1f') { // Throw error...//}

Versions of OpenSSL prior to 1.0.1g are subject to the Heartbleed vulnerability. Hence throwing an error if the version is inferior or equal to 1.0.1f.

@Tiriel
Copy link
Author

Tiriel commented May 14, 2020

Hadn't seen the old comments at the time, updated the gist accordingly in case it interests someone.

Thanks everyone!

@elzix
Copy link

elzix commented Mar 11, 2021

You're a lifesaver, thanks @Tiriel.

@Rake076
Copy link

Rake076 commented Mar 22, 2021

For newbies like me, in line 10 in encryption.js, the function takes two arguments namely text and password. password is the constant key in the file, while text is the password you will give the function to encrypt.

Moreover, I had to change $password to password in line 28.

@iNilo
Copy link

iNilo commented Feb 22, 2022

Fixed the .js decrypt function

function decrypt(text, password){
    let textParts = text.split(':');
    let iv = Buffer.from(textParts.shift(), 'hex');
    let encryptedText = Buffer.from(textParts.join(':'), 'hex');
    let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(password), iv);
    let decrypted = decipher.update(encryptedText);

    decrypted = Buffer.concat([decrypted, decipher.final()]);

    return decrypted.toString();
}

@ajayalag1974
Copy link

ajayalag1974 commented Jun 13, 2022

Hello,

Thanks for implementation in PHP & NodeJS.

But now i need implementation of decryption in Browser Javascript using CryptoJS library, i have written below code but its not working, just returning empty string, see if any body can make it work:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
function decrypt (encrypted) {
	encrypted = encrypted.split(':');
	let key = CryptoJS.enc.Utf8.parse('1234567890abcdefghijklmnopqrstuv');
	let iv = CryptoJS.enc.Hex.parse(encrypted.shift());
	let data = CryptoJS.enc.Hex.parse(encrypted.join(':'));
	data = CryptoJS.AES.decrypt({
            ciphertext: data
        },key,{iv:iv}).toString(CryptoJS.enc.Utf8);
        return data;
}
</script>

EDITED: The above code is now working, just have to provide "data" (actual encrypted string) inside an object under key "ciphertext" as a first paramater to decrypt function instead of directly passing "data".

@SATZPrincess
Copy link

@bikash-das
Copy link

How can I make the above code work for large files? I get different chunks when using php and nodejs.

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