Flashから送信される値を途中で改ざんしにくくする
改ざんしにくくしたゲーム作ってみました。→くりっくなう(スコア送信バシバシどぞ♪)
実際に、スコアを暗号化して送信しています。ポンクソフトさんのFlashを元に作成させていただきましたです。
なんも考えないでFlashのゲームを作ると、スコアランキングを作るときに、スコアをそのままベタな平文で送ってしまいがちです。そうすると、ProxyでHTTPリクエストをインターセプトして書き換えてってことをカンタンにされちゃいます。(星野君連載第5話参照)
さて、そうされないようにはどうすればいいか。
とりあえず、Rijndael(AES暗号)で暗号化してみましょう。但し、この方法はswfファイルの逆コンパイルには耐性がありません。より、イタズラできる人の範囲を少なくするといった効果です。
-----------------------
調べたけど、Flashは通信路でリクエストを書き換えられることを意識していないのか、暗号系の関数がみあたらず。。。
そこで、そんな不満を持った人が作ってくれたモジュールを拝借します♪Meychiさん多謝♪
Meychiさんのページ(英語)→http://www.meychi.com/archive/000021.php
ここから、ASCrypt library extensionを落としてきて、Rijndealを使えるようにするのです。
Flash(ActionScript)側の記述はこうなります。わからない場合は付属のサンプルflaファイルを実行してみるとよいでしょう(いやらしい人は逆コンパイルするのでキーは見えても困らない程度のものを設定するべき) 。サンプルがそうなってたので、ECBモードで記述しています。
//インポート宣言 import com.meychi.ascrypt.*; var rijndael_test:Rijndael = new Rijndael(192, 128); var rijndael_text:String = "ココに暗号化したい文字列"; var rijndael_key:String = "ココに暗号化キー"; var rijndael_hash:String = rijndael_test.encrypt(rijndael_text, rijndael_key, "ECB"); //デバッグ用には↓で見るといいかも //trace("Rijndael encrypted: "+rijndael_hash); //trace("Rijndael decrypted: "+rijndael_test.decrypt(rijndael_hash, rijndael_key, "ECB"));
これでFlash側での暗号化は完了です。rijndael_hashの文字列を思う存分サーバに投げつけてあげましょう。
さて、サーバ側では、ちゃんと受け取ってあげなければいけません。以下はPerlで受け取る例です。
use CGI; use Crypt::Rijndael; my $query = CGI->new(); my $cipher = new Crypt::Rijndael "ココにFlash側で使った暗号化キー", Crypt::Rijndael::MODE_ECB; my $crypted = $query->param('AES');#ココで暗号化された文字列を受け取る。 $crypted =~ s/([0-9A-Fa-f][0-9A-Fa-f])/pack("H2", $1 )/eg;#16進数で渡されるので戻してあげる。 my $plaintext = $cipher->decrypt($crypted); $plaintext =~ s/\00//eg;#パディング除去
そんな感じでデータの受け渡しをすれば、きっと途中で書き換えられ放題なんて間抜けなことにはなりません。
ただ、swfファイルを逆コンパイルされるとね。。。それって対策できるのかな?ま、そこは難しいから考えません。あは。