4

I have a problem with using AES decipher for a buffer object and i hope someone have an idea, what i am doing wrong...

MyExample: I have a MySQL table with AES_ENCRYPT for username and password...

CREATE TABLE Accounts 
(
    id INT(4) NOT NULL AUTO_INCREMENT,
    username VARBINARY(128) NOT NULL,
    password VARBINARY(128) NOT NULL,
    PRIMARY KEY(id)
);

DELIMITER |
CREATE TRIGGER encodeAccounts BEFORE INSERT ON Accounts
FOR EACH ROW BEGIN
    SET NEW.username = AES_ENCRYPT(NEW.username, 'password');
    SET NEW.password = AES_ENCRYPT(NEW.password, 'password');
END;

Node.JS: I am using node-mysql module to send a query to my datase:

SELECT * FROM Accounts;

Such kind of values are returned for password and username:

<Buffer 07 86 95 ee 77 df 86 50 ae 18 4c d5 3e 48 42 75>

How to decode it with Node.JS decipher method? My tries failed all... I hope AES-128-ECB is choosen correctly...

To deciper something in Node.JS should look like this:

var decipher = crypto.createDecipher('AES-128-ECB', 'password');
var dec = decipher.update(rows[i].username); // an example, value look like <Buffer ...
dec += decipher.final('utf8');
console.log('dec: ' + dec);

Thanks for all helping :)

innc
  • 41
  • 1
  • 2
  • It doesn't look like it's going to be easy, see [this page](http://coding.smashingmagazine.com/2012/05/20/replicating-mysql-aes-encryption-methods-with-php/) on how to implement MySQL's method of key expansion and padding. Can't you use `AES_DECRYPT` from inside a query? – robertklep Mar 21 '13 at 11:40
  • @robertklep surely i could use AES_DECRYPT inside a query, but if i send such a SELECT statement with a AES_DECRYPT from Node.JS to MySQL server, then my encrypted username and password would be sent back in plaintext or at least decrypted :( and i wanted avoid this... – innc Mar 21 '13 at 12:44

1 Answers1

12

Your passwords must be converted the same way MySQL will do it internally. Must results in a 16Byte-length password XORd for longer Passwords or padded with 0-Bytes. This function should do the job:

function convertCryptKey(strKey) {
    var newKey = new Buffer([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
    strKey = new Buffer(strKey);
    for(var i=0;i<strKey.length;i++) newKey[i%16]^=strKey[i];
    return newKey;
}

MySQL-compatible encryption - note to use "createCipheriv" with an empty IV. (createCipher creates an own IV which is not the same as in MySQL)

var c = crypto.createCipheriv("aes-128-ecb", convertCryptKey("myPassword"), "");
var crypted = c.update('Take a trip at galaxytrek.com :)', 'utf8', 'hex') + c.final('hex');
console.log(crypted.toUpperCase());
>> 92068A5DAECE1E080EF4BA08A45CFF8D2262401F988A9241F1E4CEAAAB80BEAF7E0B50A1D5FD57CA56E92621622F018D

Which is the same like:

mysql> select hex(aes_encrypt('Take a trip at galaxytrek.com :)','myPassword'));
+--------------------------------------------------------------------------------------------------+
| hex(aes_encrypt('Take a trip at galaxytrek.com :)','myPassword'))                                |
+--------------------------------------------------------------------------------------------------+
| 92068A5DAECE1E080EF4BA08A45CFF8D2262401F988A9241F1E4CEAAAB80BEAF7E0B50A1D5FD57CA56E92621622F018D |
+--------------------------------------------------------------------------------------------------+

Decryption

var dc = crypto.createDecipheriv("aes-128-ecb", convertCryptKey("myPassword"), "");
var decrypted = dc.update('92068A5DAECE1E080EF4BA08A45CFF8D2262401F988A9241F1E4CEAAAB80BEAF7E0B50A1D5FD57CA56E92621622F018D', 'hex', 'utf8') + dc.final('utf8');
console.log(decrypted);
>> Take a trip at galaxytrek.com :)
Denys Bogatz
  • 121
  • 1
  • 3