トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

JavaScript:CryptoJSを使って画像を暗号化・復号する のバックアップ差分(No.1)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[JavaScript:初めてのNodejs]]

*JavaScript:CryptoJSを使って画像を暗号化・復号する [#vd5c885e]

サーバ側で画像を暗号化して送信し、クライアント側で復号して表示するサンプルです。

-サーバ側はNodejs上で動作します。
-暗号化・復号には「CryptoJS」を使用します。
--https://code.google.com/p/crypto-js/

Nodejsに、暗号化・復号するための機能「Crypto」がありますが、クライアント側と併せて「CryptoJS」を使用しました。
-(参考)http://nodejs.org/api/crypto.html

***NodejsにCryptoJSを導入する [#e61d354f]

npmでインストールします

 npm install -g crypto-js

***コードスニペット [#eefe0123]

まずは関連する箇所を抜粋して解説

■暗号化(サーバ側)

-CryptoJSを読み込みます。
 CryptoJS = require('crypto-js');

-暗号化する画像の読み込みます。
 var content = fs.readFileSync("./img/images.jpg");
 var retdata;
 var contentType;

-次に、暗号化するためにUint8Arrayオブジェクトを生成します。
 var u8a = new Uint8Array(content);

-Unit8Aarryオブジェクトから暗号化のwordArrayオブジェクトを生成します。
 var srcWords = CryptoJS.enc.u8array.parse(u8a);

-AESで暗号化します。
 var encrypted = CryptoJS.AES.encrypt(srcWords, "password");

-暗号化されたオブジェクトからiv、salt、ciphertextを取り出し、クライアントへの送信用にJSONに変換します。
 var obj = {};
 obj.iv = encrypted.iv.toString();
 obj.s = encrypted.salt.toString();
 obj.ct = encrypted.ciphertext.toString(CryptoJS.enc.Base64);

-クライアントへ送信します。
 contentType = 'application/json';
 retdata = JSON.stringify(obj);
 res.writeHead(200,{"Content-Type":contentType});
 res.end(retdata);

次に、クライアント側です。

■クライアント側

-ajax通信準備
 var xhr = new XMLHttpRequest();
 xhr.open("GET", HOSTNAME+ENCRYPTO_PATH, true);
 xhr.onload = (function() {

-以下onloadのコールバック関数の中身
-受信したJSONをパース
         var obj = JSON.parse(xhr.response);

-受信したciphertextから「CipherParams」オブジェクトを生成
         var cipherParams = CryptoJS.lib.CipherParams.create({
                 ciphertext: CryptoJS.enc.Base64.parse(obj.ct)
         });
-同じく、cipherParamsオブジェクトにsalt、ivを設定
         cipherParams.salt = CryptoJS.enc.Hex.parse(obj.s);
         cipherParams.iv= CryptoJS.enc.Hex.parse(obj.iv);

-AES復号
         var decrypted =CryptoJS.AES.decrypt(  cipherParams  , "password");

-複合されて生成されたオブジェクトをUint8Arrayオブジェクトに変換&br;JpegImage(jpg.js)に喰わせるため
         var u8  = CryptoJS.enc.u8array.stringify(decrypted);

-JpegImageオブジェクトを生成し、canvasへ描画
         var j = new JpegImage();
         j.parse(u8);
         displayImage(j);
         }).bind(this);

-ajax通信開始
 xhr.send(null);

って感じです。


***ソースコード全文 [#fd36a953]

HTMLとかは適当に用意してくださいw

サーバ、クライアント順に掲載します。

■サーバ側
 var http = require("http"),
         fs = require("fs"),
         CryptoJS = require('crypto-js');
 
 var server = http.createServer(function(req,res){
 
         var content = fs.readFileSync("./img/images.jpg");
         
         var retdata;
         var contentType;
 
 console.log(req.url);
         if (req.url =='/crypto' ) {
 console.log("crypto");
 var start = Date.now();
                 var u8a = new Uint8Array(content);
                 var srcWords = CryptoJS.enc.u8array.parse(u8a);
                 var encrypted = CryptoJS.AES.encrypt(srcWords, "password");
                 var obj = {};
                 obj.iv = encrypted.iv.toString();
                 obj.s = encrypted.salt.toString();
                 obj.ct = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
 
                 contentType = 'application/json';
                 retdata = JSON.stringify(obj);
 var end = Date.now();
 console.log("encryption:" + (end-start));
         } else {
                 retdata = content;
                 contentType = 'imag/jpeg';
         }
 
         res.writeHead(200,{"Content-Type":contentType});
         res.end(retdata);
 console.log("return client");
 });
 
 
 
 server.listen(8080);
 console.log("Server started on 8080.");
 
 
 CryptoJS.enc.u8array = {
         /**
          * Converts a word array to a Uint8Array.
          *
          * @param {WordArray} wordArray The word array.
          *
          * @return {Uint8Array} The Uint8Array.
          *
          * @static
          *
          * @example
          *
          *     var u8arr = CryptoJS.enc.u8array.stringify(wordArray);
          */
                 stringify: function (wordArray) {
                     // Shortcuts
                     var words = wordArray.words;
                     var sigBytes = wordArray.sigBytes;
 
                     // Convert
                     var u8 = new Uint8Array(sigBytes);
                     for (var i = 0; i < sigBytes; i++) {
                         var bytes = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                         u8[i]=bytes;
                     }
 
                     return u8;
                 },
 
         /**
          * Converts a Uint8Array to a word array.
          *
          * @param {string} u8Str The Uint8Array.
          *
          * @return {WordArray} The word array.
          *
          * @static
          *
          * @example
          *
          *     var wordArray = CryptoJS.enc.u8array.parse(u8arr);
          */
         parse: function (u8arr) {
             // Shortcut
             var len = u8arr.length;
 
             // Convert
             var words = [];
             for (var i = 0; i < len; i++) {
                 words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
             }
 
             return CryptoJS.lib.WordArray.create(words, len);
         }
     }

■クライアント側
 var HOSTNAME = 'http://localhost:8080/';
 var ENCRYPTO_PATH = 'crypto';
 
 function getEncryptoImageData(){
 
 var start,end;
 var stime;
 start = Date.now();
 
         var xhr = new XMLHttpRequest();
         xhr.open("GET", HOSTNAME+ENCRYPTO_PATH, true);
         xhr.onload = (function() {
 end = Date.now();
 //console.log(end);
 console.log("Data recieve:" +  (end - start));
 console.log("-----------------");
 
 start = Date.now();
 stime = start;
 
 //console.log(start);
                 var obj = JSON.parse(xhr.response);
 end = Date.now();
 //console.log(end);
 console.log("JSON parse:" +  (end - start));
 
 
 start = Date.now();
 //console.log(start);
                 var cipherParams = CryptoJS.lib.CipherParams.create({
                         ciphertext: CryptoJS.enc.Base64.parse(obj.ct)
                 });
                 cipherParams.salt = CryptoJS.enc.Hex.parse(obj.s);
                 cipherParams.iv= CryptoJS.enc.Hex.parse(obj.iv);
                 var decrypted =CryptoJS.AES.decrypt(  cipherParams  , "password");
 //console.log(decrypted);
                 var u8  = CryptoJS.enc.u8array.stringify(decrypted);
 //console.log(u8);
 end = Date.now();
 //console.log(end);
 console.log("decryption:" +  (end - start));
 
 
 start = Date.now();
 //console.log(start);
                 var j = new JpegImage();
                 j.parse(u8);
 end = Date.now();
 // console.log(end);
 console.log("image parse:" +  (end - start));
 
 
 start = Date.now();
 // console.log(start);
                 displayImage(j);
                 var viewer = new ScrollViewer("#viewer");
 end = Date.now();
 // console.log(end);
 console.log("draw image to canvas:" +  (end - start));
 console.log("Client TOTAL:" +  (end - stime));
                 }).bind(this);
         xhr.send(null);
 
 }

 function displayImage(j){
         var c = $("canvas")[0];
         c.width = j.width;
         c.height = j.height;
         var ctx = c.getContext("2d");
         var d = ctx.getImageData(0,0,j.width,j.height);
         j.copyToImageData(d);
         ctx.putImageData(d, 0, 0);
 }
 
 getEncryptoImageData();