I am sending data through insecure connection between Apache and Node.js servers. I need to encrypt data in PHP and decrypt in Node.js. I've spent 2 days trying to get it to work, however I only managed to get message signing to work, no encryption. I tried passing AES128-CBC, AES256-CBC, DES, AES128, AES256 as algorithms, however nothing worked well..
I tried this in PHP:
$data = json_encode(Array('mk' => $_SESSION['key'], 'algorithm' => 'SHA1', 'username' => $_SESSION['userid'], 'expires' => $expires));
$payload = openssl_encrypt($data, 'des', '716c26ef');
return base64_encode($payload);
And in Node.js:
var enc_json = new Buffer(response[1], 'base64');
var decipher = crypto.createDecipher('des', '716c26ef');
var json = decipher.update(enc_json).toString('ascii');
json += decipher.final('ascii');
And besides wrong decrypted data I get error such as these:
TypeError: error:0606508A:digital envelope routines:EVP_DecryptFinal_ex:data not multiple of block length
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
I need a simple encryption as data is not too sensitive (no password or user data), however data should only be read by the recipient. Key length can be anything, but procedure to encrypt/decrypt has to be as simple as possible, please no IVs.
I was struggling with the same problem this week but in the opposite way (PHP encrypts -> NodeJS decrypts) and had managed to get this snippet working:
aes256cbc.js
var crypto = require('crypto');
var encrypt = function (plain_text, encryptionMethod, secret, iv) {
var encryptor = crypto.createCipheriv(encryptionMethod, secret, iv);
return encryptor.update(plain_text, 'utf8', 'base64') + encryptor.final('base64');
};
var decrypt = function (encryptedMessage, encryptionMethod, secret, iv) {
var decryptor = crypto.createDecipheriv(encryptionMethod, secret, iv);
return decryptor.update(encryptedMessage, 'base64', 'utf8') + decryptor.final('utf8');
};
var textToEncrypt = new Date().toISOString().substr(0,19) + '|My super secret information.';
var encryptionMethod = 'AES-256-CBC';
var secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
var iv = secret.substr(0,16);
var encryptedMessage = encrypt(textToEncrypt, encryptionMethod, secret, iv);
var decryptedMessage = decrypt(encryptedMessage, encryptionMethod, secret, iv);
console.log(encryptedMessage);
console.log(decryptedMessage);
aes256cbc.php
<?php
date_default_timezone_set('UTC');
$textToEncrypt = substr(date('c'),0,19) . "|My super secret information.";
$encryptionMethod = "AES-256-CBC";
$secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
$iv = substr($secret, 0, 16);
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secret,0,$iv);
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secret,0,$iv);
echo "$encryptedMessage\n";
echo "$decryptedMessage\n";
?>
The secret here to avoid falling in key/iv size/decryption problems is to have the secret of exactly 32 characters length and 16 for the IV.
Also, it is VERY important to use 'base64' and 'utf8' in NodeJS since these are the defaults in PHP.
Here are some sample runs:
$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G3ZQ40f5bSw8P9n5OtWl1t86nV5Qfh4zNRPFbsciyyHyU3Qi4Ga1oTiTwzrPIZQXLw==
2015-01-27T18:29:12|My super secret information.
zra3FX4iyCc7qPc1dZs+G3ZQ40f5bSw8P9n5OtWl1t86nV5Qfh4zNRPFbsciyyHyU3Qi4Ga1oTiTwzrPIZQXLw==
2015-01-27T18:29:12|My super secret information.
$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G6B6+8aavHNc/Ymv9L6Omod8Di3tMbvOa2B7O2Yiyoutm9fy9l0G+P5VJT9z2qNESA==
2015-01-27T18:29:15|My super secret information.
zra3FX4iyCc7qPc1dZs+G6B6+8aavHNc/Ymv9L6Omod8Di3tMbvOa2B7O2Yiyoutm9fy9l0G+P5VJT9z2qNESA==
2015-01-27T18:29:15|My super secret information.
$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G4oD1Fr5yLByON6QDE56UOqP6kkfGJzpyH6TbwZYX2oGlh2JGv+aHYUMh0qQnAj/uw==
2015-01-27T18:29:29|My super secret information.
zra3FX4iyCc7qPc1dZs+G4oD1Fr5yLByON6QDE56UOqP6kkfGJzpyH6TbwZYX2oGlh2JGv+aHYUMh0qQnAj/uw==
2015-01-27T18:29:29|My super secret information.
$ node aes256cbc.js && php aes256cbc.php
zra3FX4iyCc7qPc1dZs+G5OVCbCaUy8a0LLF+Bn8UT4X3nYbtynO0Zt2mvXnnli9dRxrxMw43uWnkh8MIwVHXA==
2015-01-27T18:29:31|My super secret information.
zra3FX4iyCc7qPc1dZs+G5OVCbCaUy8a0LLF+Bn8UT4X3nYbtynO0Zt2mvXnnli9dRxrxMw43uWnkh8MIwVHXA==
2015-01-27T18:29:31|My super secret information.
$ node aes256cbc.js && php aes256cbc.php
fdsqSyHBJjlwD0jYfOUZM2FrONG6Fk5d7FOItYEdbnaZIhhmg/apa8/jPwKFkDXD9eNqWC3w0JzY5wjtZADiBA==
2015-01-27T18:30:08|My super secret information.
fdsqSyHBJjlwD0jYfOUZM2FrONG6Fk5d7FOItYEdbnaZIhhmg/apa8/jPwKFkDXD9eNqWC3w0JzY5wjtZADiBA==
2015-01-27T18:30:08|My super secret information.
$ node aes256cbc.js && php aes256cbc.php
fdsqSyHBJjlwD0jYfOUZM4SRfi6jG5EoDFEF6d9xCIyluXSiMaKlhd89ovpeOz/YyEIlPbYR4ly00gf6hWfKHw==
2015-01-27T18:30:45|My super secret information.
fdsqSyHBJjlwD0jYfOUZM4SRfi6jG5EoDFEF6d9xCIyluXSiMaKlhd89ovpeOz/YyEIlPbYR4ly00gf6hWfKHw==
2015-01-27T18:30:45|My super secret information.
NOTE:
I use a "timestamp|message" format to avoid man in the middle attacks. For example, if the encrypted message contains an ID to be authenticated, the MitM could capture the message and re-send it every time he wants to re-authenticate.
Therefore, I could check the timestamp on the encrypted message to be within a little time interval. This way, the same message is encrypted differently each second because of the timestamp, and could not be used out of this fixed time interval.
EDIT:
Here I was misusing the Initialization Vector (IV).
As #ArtjomB. explained, the IV should be the first part of the encrypted message, and also it should be a random value.
It's also recommended to use a hmac value in a HTTP Header (x-hmac: *value*) in order to validate that the message was originated from a valid source (but this does not address the "re-send" message issue previously described).
Here's the improved version, including the hmac for php and node and the IV as a part of the encrypted message:
aes256cbc.js (v2)
var crypto = require('crypto');
var encrypt = function (message, method, secret, hmac) {
//var iv = crypto.randomBytes(16).toString('hex').substr(0,16); //use this in production
var iv = secret.substr(0,16); //using this for testing purposes (to have the same encryption IV in PHP and Node encryptors)
var encryptor = crypto.createCipheriv(method, secret, iv);
var encrypted = new Buffer(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
hmac.value = 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.value) {
var iv = new Buffer(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);
}
}
var message = 'My super secret information.';
var method = 'AES-256-CBC';
var secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
var hmac = {};
//var encrypted = encrypt(message, method, secret, hmac);
//var decrypted = decrypt(encrypted, method, secret, hmac);
var encrypted = encryptWithTSValidation(message, method, secret, hmac);
var decrypted = decryptWithTSValidation(encrypted, method, secret, hmac, 60*60*12); //60*60m*12=12h
console.log("Use HTTP header 'x-hmac: " + hmac.value + "' for validating against MitM-attacks.");
console.log("Encrypted: " + encrypted);
console.log("Decrypted: " + decrypted);
Note that crypto.createHmac(...).digest('hex') is digested with hex. This is the default in PHP for hmac.
aes256cbc.php (v2)
<?php
function encrypt ($message, $method, $secret, &$hmac) {
//$iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16); //use this in production
$iv = substr($secret, 0, 16); //using this for testing purposes (to have the same encryption IV in PHP and Node encryptors)
$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);
}
}
$message = "My super secret information.";
$method = "AES-256-CBC";
$secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
//$encrypted = encrypt($message, $method, $secret, $hmac);
//$decrypted = decrypt($encrypted, $method, $secret, $hmac);
$encrypted = encryptWithTSValidation($message, $method, $secret, $hmac);
$decrypted = decryptWithTSValidation($encrypted, $method, $secret, $hmac, 60*60*12); //60*60m*12=12h
echo "Use HTTP header 'x-hmac: $hmac' for validating against MitM-attacks.\n";
echo "Encrypted: $encrypted\n";
echo "Decrypted: $decrypted\n";
?>
Here are some sample runs:
$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: 6862972ef0f463bf48523fc9e334bb42' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==I6cAKeoxeSP5TGgtK59PotB/iG2BUSU8Y6NhAhVabN9UB+ZCTn7q2in4JyLwQiGN
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 6862972ef0f463bf48523fc9e334bb42' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==I6cAKeoxeSP5TGgtK59PotB/iG2BUSU8Y6NhAhVabN9UB+ZCTn7q2in4JyLwQiGN
Decrypted: My super secret information.
$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: b2e63f216acde938a82142220652cf59' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CSgYBBR8dkZytORm8xwEDmD9WB1mpqC3XnSrB+wR3/KW
Decrypted: My super secret information.
Use HTTP header 'x-hmac: b2e63f216acde938a82142220652cf59' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CSgYBBR8dkZytORm8xwEDmD9WB1mpqC3XnSrB+wR3/KW
Decrypted: My super secret information.
$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: 73181744453d55eb6f81896ffd284cd8' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CTGik4Lv9PnWuEg5SiADJcdKX1to0LrNKmuCiYIweBAZ
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 73181744453d55eb6f81896ffd284cd8' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CTGik4Lv9PnWuEg5SiADJcdKX1to0LrNKmuCiYIweBAZ
Decrypted: My super secret information.
$ node aes256cbc.js && php aes256cbc.php
Use HTTP header 'x-hmac: 5372ecca442d65f582866cf3b24cb2b6' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CYEITF6aozBNp7bA54qY0Ugg9v6ktwoH6nqRyatkFqy8
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 5372ecca442d65f582866cf3b24cb2b6' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==YsFRdKzCLuCk7Yg+U+S1CYEITF6aozBNp7bA54qY0Ugg9v6ktwoH6nqRyatkFqy8
Decrypted: My super secret information.
Last but not least, if you don't have openssl mod installed in php, you can use mcrypt instead with rijndael128 and pkcs7 padding (source) like this:
aes256cbc-mcrypt.php (v2)
<?php
function pkcs7pad($message) {
$padding = 16 - (strlen($message) % 16);
return $message . str_repeat(chr($padding), $padding);
}
function pkcs7unpad($message) {
$padding = ord(substr($message, -1)); //get last char and transform it to Int
return substr($message, 0, -$padding); //remove the last 'padding' string
}
function encrypt ($message, $method, $secret, &$hmac) {
//$iv = substr(bin2hex(mcrypt_create_iv(mcrypt_get_iv_size($method, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM)),0,16); //use this in production
$iv = substr($secret, 0, 16); //using this for testing purposes (to have the same encryption IV in PHP and Node encryptors)
$message = pkcs7pad($message);
$encrypted = base64_encode($iv) . base64_encode(mcrypt_encrypt($method, $secret, $message, MCRYPT_MODE_CBC, $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 pkcs7unpad(mcrypt_decrypt($method, $secret , base64_decode(substr($encrypted, 24)) , MCRYPT_MODE_CBC, $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();
//echo "Decrypted: $decrypted\n";
$msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
return substr($decrypted,19);
}
}
$message = "My super secret information.";
$method = MCRYPT_RIJNDAEL_128;
$secret = "My32charPasswordAndInitVectorStr"; //must be 32 char length
//$encrypted = encrypt($message, $method, $secret, $hmac);
//$decrypted = decrypt($encrypted, $method, $secret, $hmac);
$encrypted = encryptWithTSValidation($message, $method, $secret, $hmac);
$decrypted = decryptWithTSValidation($encrypted, $method, $secret, $hmac, 60*60*12); //60*60m*12=12h
echo "Use HTTP header 'x-hmac: $hmac' for validating against MitM-attacks.\n";
echo "Encrypted: $encrypted\n";
echo "Decrypted: $decrypted\n";
?>
Ofcourse, some tests next:
$ php aes256cbc-mcrypt.php && node aes256cbc.js
Use HTTP header 'x-hmac: 801282a9ed6b2d5bd2254140d7a17582' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v9IyatyGeNT2yebrpJZ5xH73H5fFcV1zhqhRGwM0ToGU
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 801282a9ed6b2d5bd2254140d7a17582' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v9IyatyGeNT2yebrpJZ5xH73H5fFcV1zhqhRGwM0ToGU
Decrypted: My super secret information.
$ php aes256cbc-mcrypt.php && node aes256cbc.js
Use HTTP header 'x-hmac: 0ab2bc83108e1e250f6ecd483cd65329' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v79P+j4YUl8ln8eu7FDqEdbxMe1Z7BvW8iVUN1qFCiHM
Decrypted: My super secret information.
Use HTTP header 'x-hmac: 0ab2bc83108e1e250f6ecd483cd65329' for validating against MitM-attacks.
Encrypted: YjE0ZzNyMHNwVm50MGswbQ==ipQ+Yah8xoF0C6yjCJr8v79P+j4YUl8ln8eu7FDqEdbxMe1Z7BvW8iVUN1qFCiHM
Decrypted: My super secret information.
When dealing with symmetric encryption like this, the first step is realize that it's probably going to be a huge pain in the rear - I've never, ever had it work right away, even when I was copy pasting my own code. This is mainly because encryption and decryption methods are, by design, utterly unforgiving and rarely give useful error messages. A single null character, carriage return, line feed, or dynamically converted type can silently blow the whole process up.
Knowing this, progress stepwise. I suggest the following:
First, get PHP alone working. Pass in sample text, encrypt it, immediately decrypt it, and compare it with strict equality to the original clear text variable. Are they perfectly the same? Output both, as well - are they the same type and appear perfectly unmolested? Watch out for non-printed characters - check the length and character encoding too!
Now, do the above with one more sample text that is 1 character more or less than the previous one. This debugs block size/zero-padding issues - it matters.
If that's working - and it rarely does right away, for hard to predict reasons, continue to Node.js.
In Node.js, do the same thing as you did in PHP, even if it seems like wasted effort - for extra reasons that will be obvious in a moment. Encrypt and decrypt, all together, in your Node.js. Does it work with all the same provisos given above?
Once that is done, here comes the 'fun' part: using the same encryption methods independently in Node.js and PHP, have them both output to you the 'final' ready-to-transmit cryptext that both produced.
If all is well, they should be perfectly, exactly the same. If they aren't, you have a problem with your encryption implementations and methods not being compatible between systems. Some setting is wrong or conflicting (perhaps with zero padding or a host of other possibilities, or IV, etc), or you need to try a different implementation.
If I had to guess blindly, I'd say there is an issue with the base64 encoding and decoding (it's most commonly what goes wrong). Things tend to get done twice, because it can be tricky to debug binary data types in web applications (through a browser). Sometimes things are being encoded twice but only decoded once, or one implementation will 'helpfully' encode/decode something automatically without being clear that's what it's doing, etc.
It's also possible it's a zero-padding implementation issue between Node and PHP, as suggested here: AES encrypt in Node.js Decrypt in PHP. Fail.
These last two issues are strongly suggested by your error codes. The encryption methods predict block sizes of precise length, and if they are off then that signals corruption of the data being passed to the functions - which happens if a single extra character slipped in, or if encoding is handled differently, etc.
If you step through each of the above one at a time, assuring yourself you can't rush and must check every painstaking tiny little step of the process, it should be much more clear where exactly things are going wrong, and then that can be troubleshooted.
This is codeiginiter framework default decryption equivalent js script (aes128cbc), hope this will help someone.
let crypto = require("crypto");
let secret = 'xxxxxxxxxxxxxxxxxxxx';
// ikm is initial keying material
var hkdf = function (hashAlg, salt, ikm) {
this.hashAlg = hashAlg;
// create the hash alg to see if it exists and get its length
var hash = crypto.createHash(this.hashAlg);
this.hashLength = hash.digest().length;
this.salt = salt || new Buffer(this.hashLength).fill(0).toString();
this.ikm = ikm;
// now we compute the PRK
var hmac = crypto.createHmac(this.hashAlg, this.salt);
hmac.update(this.ikm);
this.prk = hmac.digest();
};
hkdf.prototype = {
derive: function(info, size, cb) {
var prev = new Buffer(0);
var output;
var buffers = [];
var num_blocks = Math.ceil(size / this.hashLength);
info = new Buffer(info);
for (var i=0; i<num_blocks; i++) {
var hmac = crypto.createHmac(this.hashAlg, this.prk);
hmac.update(prev);
hmac.update(info);
hmac.update(new Buffer([i + 1]));
prev = hmac.digest();
buffers.push(prev);
}
output = Buffer.concat(buffers, size);
return output;
}
};
function decrypt(code)
{
if (typeof code !== 'string')
return false;
code = code.substring(128);
var buff = new Buffer(code, 'base64');
var iv = buff.slice(0, 16);
var encyptedText = buff.slice(16).toString('base64');
var _hkdf = new hkdf('sha512', null, secret);
var derive_key = _hkdf.derive('encryption', secret.length);
var key = derive_key.slice(0, 16);
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
var result = decipher.update(encyptedText, 'base64');
result += decipher.final();
return result.replace(/[']/g, '');
}
Based on #inieto answer i created two simple classes for encryption and decryption one for php and one for typescript that are easy to use.
https://github.com/5imun/Endecryptor
Just include/import them and you are ready to go.
Example for php:
#Include Endecryptor before using it
$secret = 'hxXxVEVNa3S6OQdgltNoDkbZ10b0MkQV';
$method = 'AES-256-CBC';
$valid_request_TS_interval = 100; # in seconds
$endecryptor = new Endecryptor($secret, $method, $valid_request_TS_interval );
$original_message = '{"test":"Hello, World!"}';
$endecryptor->encryptWithTS($original_message);
echo "Encrypted message: $endecryptor->temp_encrypted\n";
echo "Encrypted message hmac: $endecryptor->temp_hmac\n";
if ( $endecryptor->decryptAndValidateTS( $endecryptor->temp_encrypted, $endecryptor->temp_hmac ) ) {
echo "Original message: $original_message\n";
echo "Decrypted message: $endecryptor->temp_decrypted\n";
} else {
echo 'Description was not successful';
}
Result:
Encrypted message: MjliMmM5NzljYWQ0YjA4Mw==ULxsH1juCOrieEkiRpHY1CMkKtvSvB5X+b8E9cOcQ7yYt+SUKj+I6FjaGvYjEldt
Encrypted message: hmac: 5aa8f1b268dfef0dc2f48f1a25204e82
Original message: {"test":"Hello, World!"}
Decrypted message: {"test":"Hello, World!"}