The result is generated as soon as a customer clicks to open a bonus case. There are 5 variables that are used for this generation:
Server seed (A cryptographically secure pseudo-randomly generated string - Example: FmLhRSyET7sLqv77j2CYdFKX5svdBNjuD96GgwKTyklJVsyeN8rxPP5il0cXSy8Lna9N5uiylI25MMa2fv65Q1r4696llhbT)
Nonce (A number that is incremented every time the seed is used - Example: 1)
Client seed (A user-defined (or random by default) string - Example: wesdioufrhjrwe80u54230ihn5234iuj5340i)
Case number (The number of the case, this increments depending on the case tier - Example: 2)
Quantity (The number of tickets available in a case, 1 item = 10,000 tickets - Example: 80,000)
For the server seed, this is hashed until the customer re-generates a new one here: https://csgoempire.com/fairness via the ‘Info’ tab:
For the client seed, customers can determine what’s entered here. This can be edited to the customer’s liking here: https://csgoempire.com/fairness via the ‘Info’ tab:
For the case number and quantity, this can be found by clicking on the case type like so:
The result is then given out to the customer using the spinner. The spinner has no say over the actual result, it’s a purely visual way of displaying the pre-generated outcome.
To verify previous results, customers can use the following PHP script:
<?php
/*
* Fill in all five below and click the blue 'eval();' button.
* ------------------ */
$numberOfCase = -1;
$unhashedServerSeed = '';
$nonce = -1;
$clientSeed = '';
$qty = -1;
/* ------------------ */
if ($numberOfCase < 0 || $unhashedServerSeed == '' || $nonce < 0 || $clientSeed == '' || $qty <= 0) {
echo "Fill in details";
return;
}
define('MAX_HEX_SEGMENTS', 6);
define('HEX_SEGMENT_SIZE', 2);
define('BASE_FOR_HEX_CONVERSION', 256);
define('HASH_TYPE', 'sha256');
function calculateDecimalValue(string $preResult): float
{
$decimalValue = 0;
for ($i = 0; $i < MAX_HEX_SEGMENTS; $i++) {
$hexValue = substr($preResult, HEX_SEGMENT_SIZE * $i, HEX_SEGMENT_SIZE);
$decimalValue += hexdec($hexValue) / pow(BASE_FOR_HEX_CONVERSION, $i + 1);
}
return $decimalValue;
}
function getProvablyFairResult(string $init, string $serverSeed, int $qty): array
{
$preResult = hash_hmac(HASH_TYPE, $init, $serverSeed);
$decimalValue = calculateDecimalValue($preResult);
$result = (int) ($decimalValue * $qty) + 1;
return [
'preResult' => $preResult,
'result' => $result,
];
}
$unhashedServerSeed = preg_replace( "/\r|\n/", "", $unhashedServerSeed);
$clientSeed = preg_replace( "/\r|\n/", "", $clientSeed);
$stringToHash = "$clientSeed-$numberOfCase-$nonce";
$result = getProvablyFairResult($stringToHash, $unhashedServerSeed, $qty);
echo "Result: {$result['result']}";
Openings between April 18th 2024 and December 5th, 2023 used this code: https://3v4l.org/ecFuT
Openings between December 5th 2023 and December 9th 2019 used this code: https://3v4l.org/urEYG
Openings before December 9th 2019 used this code: https://3v4l.org/P9Qir
This can be run locally or on any PHP script runner found online. We direct customers to: https://3v4l.org/ for this, but there are plenty of options available like so:
The customer will need to edit the caseNumber, unhashedServerSeed, nonce, clientSeed & qty variables in the script to verify results.
This information can be found here: https://csgoempire.com/fairness under ‘Bonus Cases’.
For example, if we run the following script it matches up with the result logged in my bonus case history for my most recent opening:
<?php
/*
* Fill in all five below and click the blue 'eval();' button.
* ------------------ */
$numberOfCase = 0;
$unhashedServerSeed = 'GJciI6l1Eve92F7VpOxOjEzlMZdHYJZVd5ZWIhHpgCun4I8VCjTGuYvQvbxZDQf9PntbAX1Y2InPNBESUz2Is';
$nonce = 612;
$clientSeed = 'ANjPuIY3o6kDLlkViH6e610JECNNLhXK';
$qty = 80000;
/* ------------------ */
if ($numberOfCase < 0 || $unhashedServerSeed == '' || $nonce < 0 || $clientSeed == '' || $qty <= 0) {
echo "Fill in details";
return;
}
define('MAX_HEX_SEGMENTS', 6);
define('HEX_SEGMENT_SIZE', 2);
define('BASE_FOR_HEX_CONVERSION', 256);
define('HASH_TYPE', 'sha256');
function calculateDecimalValue(string $preResult): float
{
$decimalValue = 0;
for ($i = 0; $i < MAX_HEX_SEGMENTS; $i++) {
$hexValue = substr($preResult, HEX_SEGMENT_SIZE * $i, HEX_SEGMENT_SIZE);
$decimalValue += hexdec($hexValue) / pow(BASE_FOR_HEX_CONVERSION, $i + 1);
}
return $decimalValue;
}
function getProvablyFairResult(string $init, string $serverSeed, int $qty): array
{
$preResult = hash_hmac(HASH_TYPE, $init, $serverSeed);
$decimalValue = calculateDecimalValue($preResult);
$result = (int) ($decimalValue * $qty) + 1;
return [
'preResult' => $preResult,
'result' => $result,
];
}
$unhashedServerSeed = preg_replace( "/\r|\n/", "", $unhashedServerSeed);
$clientSeed = preg_replace( "/\r|\n/", "", $clientSeed);
$stringToHash = "$clientSeed-$numberOfCase-$nonce";
$result = getProvablyFairResult($stringToHash, $unhashedServerSeed, $qty);
echo "Result: {$result['result']}";
echo "Result: {$result['result']}";
By clicking onto the case, I can check that the ticket I got falls into the correct range for the item I received:
This helps prove to the customer that we pre-generated the result 10,949 as the result for this spin when they clicked open. If the provably fair script returned a different result, it would be obvious that we manipulated the result compared to what was given out to the customer.