ハッシュ値による認証方法のメモ

昔、ハッシュ値による認証用のコードを実装したのでやり方をメモしておく。

ネットゲームで不正を行う方法

ネットゲームで行うことができる不正には以下の2つがある。

  1. クライアントからサーバに送るデータを改竄する
  2. メモリの中のデータを改竄する

今回は1への対策となるハッシュ値を用いた認証について説明する。

ハッシュ認証

ハッシュ認証は、クライアントとサーバーの両方でハッシュ値を生成し、通信時にお互いのハッシュ値を照合することで通信の正当性を確認する。
ハッシュ値の元になる情報には秘密鍵・ユーザーエージェント・パラメータなどを含める。ハッシュ値を生成する為のハッシュ関数には複数の種類があり、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