Reputation: 5
The case
I have some sensitive data in MySQL DB, and I want to encrypt it when I do a SELECT statement. Then I want to decrypt it on client side with JavaScript.
Here is some example:
MySQL select statement:
SELECT HEX( AES_ENCRYPT( 'text', 'secret' ) )
Result:
CAC9877FC9203920EC4C0E8F1CB5C49C
For client side AES JavaScript decrypt implementation I’ve tried the following libraries: Crypto-js and AES Advanced Encryption Standard.
For Crypto-js I’ve followed the Mysql AES encryption parameters( described here: http://bugs.mysql.com/bug.php?id=16713) to be equal with client-side decryption parameters but it doesn’t work.
With the second library it doesn’t seem to work either.
Example 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
Example of the client-side decrypt implementation with Advanced Encryption Standard library:
Aes.Ctr.decrypt(window.atob('CAC9877FC9203920EC4C0E8F1CB5C49C'), 'secret', 128);
Result: "40^¡®bÞøgÈ"
Aes.Ctr.decrypt('CAC9877FC9203920EC4C0E8F1CB5C49C', 'secret', 128);
Result: "ӽ+) ¾ %[ø\3 "
Could you please tell me what I’m doing wrong?
According to the Thomas comments, I've decided to switch on PHP server side encryption instead of MySQL encryption.
After half a day tries finally I've managed to find a solution and the case i have already works: encrypts a string on server side with PHP and decrypts it on client side with JavaScript using the mentioned CryptoJS library.
Here is an example of the codes:
<?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);
}
}
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);
}
Server side(PHP):
$sensitiveText = "Some sensitive information";
$encString = Encryption::encrypt($sensitiveText);
echo $encString;
Client side(JavaScript):
var decrypted = decryptData('<?=$encString;?>');
Don not forget to load the appropriate CryptoJS libraries: CBC && ZeroPadding This post help me a lot: http://lalengueta.blogspot.com/2013/07/test-criptografico-php-mcrypt-y.html You can find information for the opposite scenario as well.
Upvotes: 0
Views: 1772
Reputation: 55253
The MySQL docs you linked mention that the encryption mode that is used in MySQL is ECB, yet, you're using CTR in your decryption code.
You might want to switch to ECB.
ECB is a very unsafe encryption mode, you should not use ECB to encrypt any sensitive data.
Consider encrypting in your server-side code, not in MySQL, so as to use a more reliable encryption mode (I'd recommend CBC or CTR for simplicity).
Upvotes: 1