Bat Bayan
Bat Bayan

Reputation: 5

Mysql AES_ENCRYPT => client side JavaScript Aes.Ctr.decrypt issue

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?

UPDATE

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

<?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;?>');

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

Answers (1)

Thomas Orozco
Thomas Orozco

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.

Big, Fat, Warning: Don't use 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

Related Questions