コンテンツ保護用の難読化jQueryプラグインを公開

HTML5が流行っていますが、割と社会ではFlashが好まれます。なぜかというと、難読化なんかのノウハウがFlashでたまっているとか、そういう理由があります。

MissingLinkではHTML5のノベルゲームエンジンを作ってましたが、それはコンテンツ保護はできず、シナリオを抜こうと思えばいくらでも抜ける、そんな状態でした。
一応コピペはできない(右クリックはおろか、選択もできないし、JSをオフにすると文字がでない)ようになっていましたが、問題はコンテンツの部分でした。コンテンツはJSONで書かれており、ダウンロードしようと思えばできます。
その生データを読みにくくできないかということで、1時間くらいで書いたのがこれです。
ぶっちゃけ、ブラウザのHTML要素の部分をエンドポイントまで難読化しているもので、HTMLソースを見ていただけるとわかるように、XOR難読化されています。解読をするには、jQueryプラグインで$.javascrypt()というメソッドを実行する必要があります。
それによって難読化された要素が動的に復号化され、表示上は平文が表示されます。
以下のデモでは、クリックをすることによって解読処理がなされますが、もちろん$(document).ready()で読み込み直後にメソッドを実行することが可能です。

デモとソースコード

デモ: https://web.missinglink.co.jp/keiya/javascrypt/
ソースコード: https://github.com/MissinglinkCorp/javasCrypt
ライセンスは修正BSDです。

サーバ側のPHPソースコード例

全文: https://github.com/MissinglinkCorp/javasCrypt/blob/master/index.php

<div><span class='_k_javascrypt'><?php echo $encrypted ?></span></div>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script>
<script src="https://web.missinglink.co.jp/keiya/javascrypt/jquery.javascrypt.js"></script>
<script>
		$('#dec').click(function(e){
			$('._k_javascrypt').javascrypt();
			$(this).hide();
		});
</script>

仕組み上、サーバとクライアントの時計がたぶん99秒以上ずれるとコンテンツの解読ができなくなります。この値はもっと厳しくすることが可能です。ソースコードを改造すると、1秒までしか許容できないようにすることが可能です。PHP側のコードを工夫すれば1msでもできるかもしれませんが、ネットワークの遅延があるので実用できないと思います。
この仕組みによってサーバから送信され時間が経ったコンテンツ、つまり保存したコンテンツを解読するのは難しくなります(ただ読み込んだ時間を控えていれば解読は可能です)。解読するにはブラウザのエクステンションなどで読み込んだ直後に難読化のシード(種)と難読化文を読み取る仕組みが必要となるわけです。

HTML5ノベルゲームの例では、暗号化JSONをJavaScriptで動的に読み込んで解読させるコードを追加する予定ですが、これによってChromeでInspectorを起動して何のJSONが読み込まれているのか判断し、ダウンロードして読もうとすると、わけのわからない数字の配列があるためにあきらめる、くらいにはできると思います。まぁ、これは暗号ではないので、すぐに解読できますし、ある程度のスキルがあればブラウザエクステンションなどをつくっていくらでもほじくりまわせるとは思います。
これに関しては「私的利用上の」DVDのリッピングや「私的利用上の」ノベルゲームからのシナリオ抽出と同じ部類に入ると思いますし、いたちごっこですので仕方ないと思います。(何せ、クライアント側のソースコードがオープンなのですからね。。)

注意点ですが、もちろんコンテンツの安全性を保障するわけではないので、クレカや住所などにつかわないでください。

今後は、JPEGやPNG、MP3などを独自のフォーマットにするコンテンツ保護を考えてみようと思います。幸い、HTML5のAPI(というか次世代のECMAScriptの仕様?)にArrayBufferという、バイナリを扱うクラスがありますので、それがつかえるんじゃないかと、適当に考えています。

MongoDBのメモ

コレクション

テーブルに相当するのがコレクション。
コレクションには普通のコレクション以外にcappedコレクションというコレクションの種類がある。高速で、コレクションに挿入された順を保持する。コレクションを作る際にサイズを指定しなければならない。

サイズに到達すると古いものから消される。
cappedコレクションからデータを削除できない。コレクションごとdropする必要がある。

インデックス

RDBおなじみのインデックス。使い勝手は似ているっぽい。

インデックスの文字列評価はcase-sensitive

http://www.mongodb.org/pages/viewpage.action?pageId=5800049

MongoDBさわってみて思ったこと

感じとしてはJSONのキーの部分で検索ができるようになった、というところ。スキーマを気にせずデータを放り込めるし、それでいて検索は楽にできる。これは素晴らしい。

この性質は、Facebook APIやTwitter APIのJSONをほうり投げる際に便利で、RDBでやっていた面倒なことすべてがばからしく思える。

問題はデータの整合性。RASISのI:Integrityの部分。なんか基本オンメモリで、数十秒に一度のディスクへのflushするらしいので、それでプロセスがコケるとデータが飛ぶとか。最近のバージョン1.8からはjournalingがついたようなんだが、それでデータ破損は抑えられたのだろうか。

あとAuto-sharding周りが不安定だと聞く。前にFoursquareで起きたトラブルもそれに起因するとか。

いずれにせよあと数年は人柱の覚悟が必要だろうなー、まあ次作るサイトで使うんだけど。