ネタが無いので、ありきたりだけどちょっと前にやってたことをブログに書こう。
CryptoJSはクライアントサイド(つまりはブラウザ上)でAESなんかを使った暗号化が可能なJavascriptライブラリです。
SHA-1などのハッシュ関数もあり、クライアント上でお手軽暗号化が実装できます。
使うのか知らないですがRIPEMDとかSHA-3まで対応してます。
文字列のAES暗号化・複合
SHA-2でパスフレーズをハッシュ化し、文字列をbase64エンコードしAES暗号化します。
ここまでやればまずパスフレーズがわからないなら暗号が破られることはないでしょう。
こんな感じのhtmlを用意。html部分は省略します。
上がパスフレーズ、下が暗号化する文字列です。
めんどいのでjquery使ってます。
window.onload = function () { $("#set").on("click", function () { var text = $("#input").val(); var str = CryptoJS.SHA256(text); var hashbase64 = str.toString(CryptoJS.enc.Base64); //AES var Message = $("#text").val(); encrypt = CryptoJS.AES.encrypt(Message, hashbase64); console.log("aes encrypt:"); console.log(encrypt.toString()); decrypt = CryptoJS.AES.decrypt(encrypt, hashbase64); console.log("aes decrypt:"); console.log(decrypt.toString(CryptoJS.enc.Utf8)); }); };
そのままbase64で出力できるのが便利です。
※base64で出力するには、enc-base64-min.jsが必要です。
画像のAES暗号化・複合
画像も同じように、DataURIスキーマに変換すれば使えます。
アップロードした画像なんかを暗号化させたいので、
HTML5 File APIでまず画像を読み込んで処理します。
window.onload = function () { $("#imgset").on("change", function () { var filesrc = $(this).prop('files')[0]; if (!filesrc) { console.error("No File Error!"); return; } // ファイル未選択 if (filesrc.size >= 307200) { console.error("File Size Over Error!"); return; } // サイズ制限300KBまで console.log(filesrc); var fr = new FileReader(); fr.onload = function () { src = fr.result; // 読み込んだ画像データをsrcにセット $('#preview_field').attr('src', src); } fr.readAsDataURL(filesrc); // 画像読み込み }); $("#imgupload").on("click", function () { var text = $("#input").val(); var str = CryptoJS.SHA256(text); var hashbase64 = str.toString(CryptoJS.enc.Base64); //AES var Message = $("#preview_field").attr('src'); encrypt = CryptoJS.AES.encrypt(Message, hashbase64); console.log("aes encrypt:"); console.log(encrypt.toString()); decrypt = CryptoJS.AES.decrypt(encrypt, hashbase64); console.log("aes decrypt:"); console.log(decrypt.toString(CryptoJS.enc.Utf8)); }); };
複合したDataURIスキーマをクリックするとちゃんと画像が表示され、問題なく複合できていることがわかります。
しかし画像はそもそも文字と比べると容量がケタ違いですので、300KB程度では一瞬ですが、
数MBの画像を処理したりすると時間掛かるかもしれないです。
これをそのまま受け渡したりサーバに投げて処理できれば、暗号化した通信がhttps無しで実装できますね!まあhttps使えばいいじゃんって話ですが。
FK says:
httpsで通信が暗号化されてもサーバーに置いたら暗号化されないよ。
この暗号はサーバーにおいても暗号化されていますよね。
potpro says:
httpsはデータをクライアントから送信した場合、クライアントで暗号化、サーバで復号しますが、この場合はパスフレーズがわからなければ、サーバ側では復号できませんね。
httpsとは別に、別の観点でセキュリティ的に応用できそうです。