Skip to content

Instantly share code, notes, and snippets.

@cretueusebiu
Last active January 9, 2017 20:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cretueusebiu/3d18629110281aec043a0848e1761c3f to your computer and use it in GitHub Desktop.
Save cretueusebiu/3d18629110281aec043a0848e1761c3f to your computer and use it in GitHub Desktop.
<?php
class IdentityVerifier
{
const CERT_DOWNLOAD_ERR = 1;
const CERT_PUB_KEY_ERR = 2;
const SIGNATURE_INCORRECT = 3;
const SIGNATURE_ERR = 3;
protected $error = 0;
protected $signature;
protected $certificate;
public function playerId($playerId)
{
$this->playerId = $playerId;
return $this;
}
public function signature($signature)
{
$this->signature = $signature;
return $this;
}
public function salt($salt)
{
$this->salt = $salt;
return $this;
}
public function certificate($certificate)
{
$this->certificate = $signature;
return $this;
}
public function bundleId($bundleId)
{
$this->bundleId = $bundleId;
return $this;
}
public function timestamp($timestamp)
{
$this->timestamp = $timestamp;
return $this;
}
/**
* Verifiy the player identity.
*
* @return bool
*/
public function verify()
{
if (filter_var($this->certificate, FILTER_VALIDATE_URL) !== false) {
$this->certificate = file_get_contents($this->certificate);
if ($this->certificate === false) {
$this->error = static::CERT_DOWNLOAD_ERR;
return false;
}
}
if (($pubKeyId = $this->pubKey()) === false) {
$this->error = static::CERT_PUB_KEY_ERR;
return false;
}
$data = $this->playerId . $this->bundleId . $this->toBigEndian($timestamp) . $this->salt;
$result = openssl_verify($data, $this->signature, $pubKeyId, OPENSSL_ALGO_SHA256);
if ($result === 1) {
return true;
}
if ($result === 0) {
$this->error = static::SIGNATURE_INCORRECT;
} else {
$this->error = static::SIGNATURE_ERR;
}
return false;
}
protected function pubKey()
{
$pem = $this->cer2pem($this->certificate);
return openssl_pkey_get_public($pem);
}
protected function downloadCert($url)
{
return file_get_contents($url);
}
protected function cer2pem($data)
{
$pem = chunk_split(base64_encode($data), 64, "\n");
return "-----BEGIN CERTIFICATE-----\n{$pem}-----END CERTIFICATE-----\n";
}
protected function toBigEndian($timestamp)
{
if (PHP_INT_SIZE === 4) {
$hex = '';
do {
$last = bcmod($timestamp, 16);
$hex = dechex($last) . $hex;
$timestamp = bcdiv(bcsub($timestamp, $last), 16);
} while ($timestamp > 0);
return hex2bin(str_pad($hex, 16, '0', STR_PAD_LEFT));
}
$highMap = 0xffffffff00000000;
$lowMap = 0x00000000ffffffff;
$higher = ($timestamp & $highMap) >>32;
$lower = $timestamp & $lowMap;
return pack('N2', $higher, $lower);
}
/**
* Get the last error code.
*
* @return int
*/
public function lastErrorCode()
{
return $this->error;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment