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のコードも作成していて、全て互換性を持たせているので、そのうちに公開して行く予定です。
0 件のコメント:
コメントを投稿