ソーシャルゲームの通信をセキュアにする方法

ソーシャルゲームの通信をセキュアにする方法について、昔学習したことを忘れないうちに記事に起こすことにした。

ソーシャルゲームでチートを行う方法

一般的にソーシャルゲームで行われるチートには以下のようなものがある。

  1. クライアントからサーバに送るデータを改竄する
  2. サーバからクライアントに送るデータを改竄する
  3. メモリに展開されたデータを改竄する

今回はこれらのうち1と2への対策となるハッシュ値での認証方法について説明する。

ハッシュ認証

ソーシャルゲームなどで不正防止を行う為に認証を設けたい場合、ハッシュ値を用いた認証方法が挙げられる。 ハッシュ認証は、クライアントとサーバーの両方でハッシュ値を生成し、通信時にお互いのハッシュ値を照合することで通信の正当性を確認する。
ハッシュ値の元になる情報には秘密鍵・ユーザーエージェント・パラメータなどを含める。ハッシュ値を生成する為のハッシュ関数には複数の種類があり、2013年10月現在ではSHA-2のSHA-256がデファクトスタンダードとなっている。

ハッシュ認証の仕組み

クライアント側

送信したいデータをもとにハッシュ値を生成しておき、データとハッシュ値を一緒にサーバに送信する。

サーバ側

送信されてきたデータとハッシュ値を受け取り、データから更にハッシュ値を生成する。受け取ったハッシュ値とデータから生成したハッシュ値が一致した場合は処理を行う。

イメージが湧きやすいように実際にサーバサイドで実行するプログラムの例を以下に示す。

<?php /* * ハッシュ認証を行うサーバサイドプログラム */

//秘密鍵
$SECRET_KEY = 'W4IyR8If75QVj3UHQ2jMdG';

//ユーザーエージェント名
$USER_AGENT = 'SmokyDogAPI';

//クライアントから送られてきたデータ
$clientParam = $_POST['submit']['parameter'];

//クライアントから送られてきたクライアント側で生成したハッシュ値
$clientHash = $_POST['submit']['hash'];

//秘密鍵・ユーザーエージェント・パラメータを繋げてサーバー側のハッシュ値を生成する
$serverHash = hash('sha256', $SECRET_KEY.$USER_AGENT.$clientParam);

if($clientHash === $serverHash){
    //認証成功の処理
}else{
    //認証失敗の処理
}

上記はクライアントからサーバにデータを送る場合の対策である。サーバからクライアント側にデータを送る場合も同様に、サーバ側で送信したいデータをもとにハッシュ値を生成しておき、データとハッシュ値を一緒にクライアントに送信する。そしてクライアント側で認証を行う。

クライアント側のコードを難読化したほうが良い

ゲームで不正が行われる方法の一つとして、クライアントをデコンパイルし、ハッシュ認証に使う秘密鍵を盗む方法がある。それを防止する方法としてコードの難読化が挙げられる。

この記事だけではまとめきれないので、ここでは紹介まで。

参考
https://www.otwo.jp/blog/cheat_measures/
https://www.slideshare.net/ssuser741a3c/ss-62940759