データをシーザー暗号化でまあまあセキュアな通信を行えるJSとPHPの互換コードを作ったよ

2018/05/11

Javascript PHP テクノロジー プログラミング 特集

t f B! P L
WEBサービスでTLS(SSL)を使う事が必須になりかけている昨今ですが、データ通信をハッキングされるよりも、根本的にデータのやりとりを平文で行う方がよっぽどやばいです。 GETリクエストで、個人情報など送ってしまったら、httpsプロトコルでもなんの意味もありません。 また、ブラウザのcookieやlocalstorageにデータを保存するときに、平文で保存しておく事も、簡単にユーザー側で改竄できてしまうので、そうした時のために、ある程度の暗号化を行っておくことは必須です。 今回は、シーザー暗号化という、文字コードを任意のバイト数分シフトさせて簡易暗号化する方式を使って、便利にデータを扱えるようにしてみましょう。

シーザー暗号化を使う目的

・データを見た目の難読化する事で、簡単に改竄できないようにする。 ・目に見えるcookieやlocalstorageなどでも、不自然じゃ無いようにデータ保存を行う。 ・ブラウザローカルと、サーバーサイドでどちらでもエンコード、デコードができるようにして、データを扱いやすくする。
ただし、シーザー暗号化とは、任意バイト数のコードシフトなので、内容判別は意外と簡単にデコードできたりもします。 実際に使うコツとしては、シーザー暗号化に加えて別の仕組みを加えることで、かなり解読が難しくなるのですが、今回はストレートにシーザー暗号化だけをプログラミングします。 ちなみに、SHA3やbase64やブローフィッシュなどの暗号化での難読かもメジャーどころですが、エンコード、デコードの元コードで読み込むライブラリが大きいものはWEBサービスで使う場合に無駄なトラフィックが掛かるため、こうしたコスト削減も踏まえての「シーザー暗号」です。

ブラウザサイド(javascript)コード

(function(){ var $$ = function(){}; /* シーザーー暗号化 */ $$.prototype.encode = function(val, key) { if(!key){key = 3;} val = encodeURIComponent(val); var result = ""; for (var i = 0; i < val.length; i++) { result += String.fromCharCode(val.charCodeAt(i) + key); } return result; }; /* シーザー復号化 */ $$.prototype.decode = function(val, key) { if(!key){key = 3;} var result = ""; for (var i = 0; i < val.length; i++) { result += String.fromCharCode(val.charCodeAt(i) - key); } return decodeURIComponent(result) ; }; window.$$CAESAR = $$; })(); // test var val = "あいうえおabcde"; var caesar = new $$CAESAR; var enc = caesar.encode(val , 3); console.log(enc); var dec = caesar.decode(enc , 3); console.log(dec); これをデバッグコンソールで実行すると、以下のような結果が得られます。 (H6(;4(;5(H6(;4(;7(H6(;4(;9(H6(;4(;;(H6(;4(;Ddefgh あいうえおabcde 1行目がエンコード結果で、2行目がそれをさらにデコードした結果になります。 日本語サイトに嬉しい、マルチバイトにも対応させているため、全角入り混じった状態での暗号化が可能になります。 個別データで圧縮するのもいいですが、保存するjsonデータなどを一括で圧縮する方が便利に使えるかもしれませんね。

サーバーサイド(PHP)プログラム

続いて、ブラウザ側で圧縮したデータをサーバー側でデコードできないと、データが扱いづらいので、PHPバージョンも書いてみました。 <?php namespace ARCHIVE; class Caesar{ /* シーザーー暗号化 */ public static function encode($val , $key=3){ if($val === ""){return null;} $val = urlencode($val); $result = ""; for ($i = 0; $i < strlen($val); $i++) { $str = substr($val , $i , 1); $result .= chr(ord($str) + $key); } return $result; } /* シーザー復号化 */ public static function decode($val , $key=3){ if($val === ""){return null;} $result = ""; for ($i=0; $i < strlen($val); $i++) { $str = substr($val , $i , 1); $result .= chr(ord($str) - $key); } return urldecode($result); } } // test $val = "あいうえおabcde"; $caesar = new \ARCHIVE\Caesar; $enc = $caesar->encode($val); echo $enc.PHP_EOL; $dec = $caesar->decode($enc); echo $dec.PHP_EOL; ターミナルでCLIコマンド実行してみた結果です。 $ php caesar.php (H6(;4(;5(H6(;4(;7(H6(;4(;9(H6(;4(;;(H6(;4(;Ddefgh あいうえおabcde javascriptと同じ元データから、同じ結果になっている事がわかります。 逆にPHP側で圧縮したデータを安全にブラウザに送って、それを簡単にデコードする事もできます。 こうした思考を入れて、データの扱いをいかにセキュア且つ、簡易にできるかが、システム運用において重要であると考えられます。 ちなみに、このシーザー暗号化は、python2,3とrubyのコードも作成していて、全て互換性を持たせているので、そのうちに公開して行く予定です。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ