CryptoJSを使ったクライアントとサーバー間の暗号化と復号化

CryptoJSを使ったクライアントサイド(Javascript)とサーバーサイド(Node.js)での暗号化と復号化について。CryptoJSはbrix/crypto-jsのやつを使用します。

クライアントサイドの実装

CryptoJSのライブラリ(crypto-js.js)をheadで読み込ませているとします。

var str = "Lorem ipsum dolor sit amet";
var key = "12345678901234567890123456789012";
var encrypted = CryptoJS.AES.encrypt(str, key);
console.log(encrypted.toString());

encryptメソッドで生成した変数をtoString()すると、ciphertextやiv、saltなど復号化に必要なものをまとめて一つのBase64フォーマットの文字列に変換してくれます(例:U2FsdGVkX19c2KuWxFQsC9fhaum9z8w6MtoMikCmy0Om+Mi+cAEEFu7JZl8JLOf3)。これをNode.js側に送ります。

サーバーサイドの実装

var CryptoJS = require('crypto-js');
var str = "U2FsdGVkX19c2KuWxFQsC9fhaum9z8w6MtoMikCmy0Om+Mi+cAEEFu7JZl8JLOf3";
var key = "12345678901234567890123456789012";
var decrypted = CryptoJS.AES.decrypt(str, key);
console.log(decrypted.toString(CryptoJS.enc.Utf8));

という感じで、CryptoJSを使うと簡単に暗号化と復号化ができます。ただ、クライアントサイドのソースは公開されてしまうので、クライントサイドとサーバーサイドでどうkeyを共有するかというのが考えどころ(ajaxで取得するようにするとか?)。また、keyはsaltingした上で使うらしいので([JavaScript]CryptoJSでAES暗号のsaltとパスフレーズからkeyを求める - Qiita参照)、他の暗号化/復号化ライブラリと連携して使おうとすると、実際使われているkeyがわからなくて難儀するかもなあと思いました。

追記

いわゆるブラウザ(クライアントサイド)とサーバーサイドで暗号化してやりとりするなら、公開鍵の方がいいよねと今さらながら思った。そしてCrypticoなら、サーバーサイド(Node.js)で公開鍵を生成して、クライアントサイドに送信、それを使ってクライアントサイドで暗号化して、送り返すということができそう。そのうち試してみたい。

あとうっかり失念していたけど、標準のWeb CryptographyCan I use... Support tables for HTML5, CSS3, etcを見ると、なかなかいい感じのサポート具合になっている。このあたりもそのうち見直してみたい(そのうち...)