The issue at hand
I have confidential data stored in a MySQL database, and I am looking to encrypt this data when performing a SELECT query. Subsequently, I aim to decrypt it on the client-side using JavaScript.
Here is an example:
MySQL SELECT query:
SELECT HEX( AES_ENCRYPT( 'text', 'secret' ) )
Result:
CAC9877FC9203920EC4C0E8F1CB5C49C
I have explored utilizing two libraries for implementing client-side AES decryption: Crypto-js and AES Advanced Encryption Standard.
While attempting to align the encryption parameters between MySQL and Crypto-js library as described in this link, I encountered issues with my solution not working as anticipated.
Even with the second library, I faced similar challenges.
Sample code using Crypto-js:
CryptoJS.AES.decrypt(
'CAC9877FC9203920EC4C0E8F1CB5C49C',
'secret',
{
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.ZeroPadding
}
);
Result:
WordArray.t.extend.init
{
words: Array[8],
sigBytes: 24,
init: function,
toString:function,
concat: function…
}
sigBytes: 24
words: Array[8]
0: -140444473
1: 2005116093
2: -506226828
3: -210568886
4: -277754559
5: 880241217
6: 598097705
7: -2102072885
length: 8
__proto__: Array[0]
__proto__: s
Client-side decryption implementation using Advanced Encryption Standard library:
Aes.Ctr.decrypt(window.atob('CAC9877FC9203920EC4C0E8F1CB5C49C'), 'secret', 128);
Result: "40^¡®bÞøgÈ"
Aes.Ctr.decrypt('CAC9877FC9203920EC4C0E8F1CB5C49C', 'secret', 128);
Result: "ӽ+) ¾ %[ø\3 "
What could be causing this discrepancy?
UPDATE
Following advice from Thomas, I have opted to implement PHP server-side encryption instead of relying solely on MySQL encryption.
After extensive trial and error, I successfully found a solution that enables me to encrypt data on the server-side using PHP and decrypt it client-side using the CryptoJS library.
See below for code examples:
PHP
<?php
class Encryption
{
public function encrypt($text){
$key = md5("secret");
$iv = utf8_encode("1234567812345678");
return mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$key,
$text,
MCRYPT_MODE_CBC,
$iv);
}
}
JavaScript
function decryptData(text){
var hash = CryptoJS.MD5('secret');
var key = CryptoJS.enc.Utf8.parse(hash);
var iv = CryptoJS.enc.Utf8.parse('1234567812345678');
var dec = CryptoJS.AES.decrypt(
text,
key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
});
return CryptoJS.enc.Utf8.stringify(dec);
}
How to use it
Server side(PHP):
$sensitiveText = "Some sensitive information";
$encString = Encryption::encrypt($sensitiveText);
echo $encString;
Client side(JavaScript):
var decrypted = decryptData('<?=$encString;?>');
Make sure to load the appropriate CryptoJS libraries: CBC && ZeroPadding. A helpful resource for me was: this post. It provides insights on cryptographic testing with PHP mcrypt and offers guidance for different scenarios as well.