I'm trying to decrypt a string in PHP which was originally encrypted in NodeJS.
PHP:
openssl_decrypt($raw_id, "aes-128-cbc", "s7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m", 0, null)
This seems to always returnfalse
.
Encryption in Nodejs:
function encrypt(text) {
var cipher = crypto.createCipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
var encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
return encrypted;
}
function decrypt(text) {
var cipher = crypto.createDecipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
var decrypted = cipher.update(text, 'hex', 'utf8')
decrypted += cipher.final('utf8');
return decrypted;
}
I basically want to encrypt, for example, encrypt("Pizza")
in Nodejs, send it to the PHP page (3879f91a59e9a458db62f905b0a488a1
), and decrypt it from there (openssl_decrypt: return Pizza
).
I know this code is not safe, since I'm not using an IV but I'm not sure how to add one.
Your method is not secure and can also be victim to man in the middle attacks, you should always use a IV and a HMAC
You can encrypt in php like this
$key = substr('encyptionsec123342',0,32)
function encrypt ($message, $method, $secret, &$hmac) {
$iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16);
$encrypted = base64_encode($iv) . openssl_encrypt($message, $method, $secret, 0, $iv);
$hmac = hash_hmac('md5', $encrypted, $secret);
return $encrypted;
}
function decrypt ($encrypted, $method, $secret, $hmac) {
if (hash_hmac('md5', $encrypted, $secret) == $hmac) {
$iv = base64_decode(substr($encrypted, 0, 24));
return openssl_decrypt(substr($encrypted, 24), $method, $secret, 0, $iv);
}
}
function encryptWithTSValidation ($message, $method, $secret, &$hmac) {
date_default_timezone_set('UTC');
$message = substr(date('c'),0,19) . "$message";
return encrypt($message, $method, $secret, $hmac);
}
function decryptWithTSValidation ($encrypted, $method, $secret, $hmac, $intervalThreshold) {
$decrypted = decrypt($encrypted, $method, $secret, $hmac);
$now = new DateTime();
$msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
return substr($decrypted,19);
}
}
This is a secure AES-256-CBC method and with HMAC to stop man in the middle attacks.
Node.js
var secret = "encyptionsec123342";
secret = secret.substr(0, 32);
var method = 'AES-256-CBC';
var encrypt = function(message, method, secret, hmac) {
var iv = crypto.randomBytes(16).toString('hex').substr(0, 16);
var encryptor = crypto.createCipheriv(method, secret, iv);
var encrypted = new Buffer.alloc(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
hmac = crypto.createHmac('md5', secret).update(encrypted).digest('hex');
return encrypted;
};
var decrypt = function(encrypted, method, secret, hmac) {
if (crypto.createHmac('md5', secret).update(encrypted).digest('hex') == hmac) {
var iv = new Buffer.from(encrypted.substr(0, 24), 'base64').toString();
var decryptor = crypto.createDecipheriv(method, secret, iv);
return decryptor.update(encrypted.substr(24), 'base64', 'utf8') + decryptor.final('utf8');
}
};
var encryptWithTSValidation = function(message, method, secret, hmac) {
var messageTS = new Date().toISOString().substr(0, 19) + message;
return encrypt(messageTS, method, secret, hmac);
}
var decryptWithTSValidation = function(encrypted, method, secret, hmac, intervalThreshold) {
var decrypted = decrypt(encrypted, method, secret, hmac);
var now = new Date();
var year = parseInt(decrypted.substr(0, 4)),
month = parseInt(decrypted.substr(5, 2)) - 1,
day = parseInt(decrypted.substr(8, 2)),
hour = parseInt(decrypted.substr(11, 2)),
minute = parseInt(decrypted.substr(14, 2)),
second = parseInt(decrypted.substr(17, 2));
var msgDate = new Date(Date.UTC(year, month, day, hour, minute, second))
if (Math.round((now - msgDate) / 1000) <= intervalThreshold) {
return decrypted.substr(19);
}
}
To perform encryption and decryption in php,
$encrypted = encryptWithTSValidation($recipent, $method, $key, $hmac);
$decrypted = decryptWithTSValidation($encrypted,$method,$key, $hmac, 60*60*12)//this is 12 hours
to generate a hmac, you can use simple md5 hashing
$hmac = hash_hmac('md5', $recipent, $key);
and in node.js
var decrypted = decryptWithTSValidation(encString, method, secret, hmac, 60 * 60);
var encrypted = decryptWithTSValidation(string, method, secret, hmac);
NOTE: Make sure to make a unique key that is of 32 bit and is same while encryption and decryption in nodejs and php. Also keep it safe and never store it in a database.
Code Reference : Encrypt string in PHP and decrypt in Node.js