Node.jsでMySQLのAES Encrypt/Decrypt

MySQL上でAES_ENCRYPT()されたものをNode.js上でDecryptする方法です。同様にEncryptの方法もまとめておきます。
sha1/md5/Bcrypt等のハッシュは過去記事にあります。

他のハッシュの場合と同じくcryptoを使います。

var crypto = require('crypto');

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;
}

var c = crypto.createCipheriv("aes-128-ecb", convertCryptKey("myPassword"), "");
var crypted = c.update('ZeBeVogue別館', 'utf8', 'hex') + c.final('hex');
console.log(crypted.toUpperCase());

var dc = crypto.createDecipheriv("aes-128-ecb", convertCryptKey("myPassword"), "");
var decrypted = dc.update(crypted.toUpperCase(), 'hex', 'utf8') + dc.final('utf8');
console.log(decrypted);

実行してみます。

$ node app.js 
5CDF7EEA93FA43B5E7757BABA610EE3F
ZeBeVogue別館

Encryptされたものと、それをDecryptしたものが出力されました。
ちゃんと元に戻っています。

では、crypted.toUpperCase()がMySQLが生成するものと比較してみます。

mysql> select hex(aes_encrypt('ZeBeVogue別館','myPassword'));
+--------------------------------------------------+
| hex(aes_encrypt('ZeBeVogue別館','myPassword'))   |
+--------------------------------------------------+
| 5CDF7EEA93FA43B5E7757BABA610EE3F                 |
+--------------------------------------------------+
1 row in set (0.00 sec)

同じになりました。

最後に上記の文字列で元に戻るかスクリプトを変更しても同じになる事が確認できると思います。

var dc = crypto.createDecipheriv("aes-128-ecb", convertCryptKey("myPassword"), "");
var decrypted = dc.update('5CDF7EEA93FA43B5E7757BABA610EE3F', 'hex', 'utf8') + dc.final('utf8');
console.log(decrypted);