How are case openings fair?

Information about how case openings are provably fair

smz avatar
Written by smz
Updated over a week ago

The result is generated as soon as a customer clicks to open a 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)

  • 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 four below and click the blue 'eval();' button.
* ------------------ */

$unhashedServerSeed = '';
$nonce = -1;
$clientSeed = '';
$ticketQuantity = -1;

/* ------------------ */

if ($unhashedServerSeed == '' || $nonce < 0 || $clientSeed == '' || $ticketQuantity <= 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);
$nrand = strlen($clientSeed);
$stringToHash = "$clientSeed-$nrand-$nonce";

$result = getProvablyFairResult($stringToHash, $unhashedServerSeed, $ticketQuantity);

echo "Result: {$result['result']}";

Openings before April 18th 2024 used this code: https://3v4l.org/CQLj9

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 unhashedServerSeed, nonce, clientSeed & qty variables in the script to verify results.

This information can be found here: https://csgoempire.com/fairness under ‘Cases’.

For example, if we run the following script it matches up with the result logged in my case history for my most recent opening:

<?php
/*
* Fill in all four below and click the blue 'eval();' button.
* ------------------ */

$unhashedServerSeed = '0ECovoExJzCTJuCKxzvJ3urgDKmOU61hkvkDOUASeE8R4eySoOdDnswdmXAsVuMFnVYZxT6BEYjMvVNa9i5HBofCY1n';
$nonce = 30;
$clientSeed = 'test';
$ticketQuantity = 100000;

/* ------------------ */

if ($unhashedServerSeed == '' || $nonce < 0 || $clientSeed == '' || $ticketQuantity <= 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);
$nrand = strlen($clientSeed);
$stringToHash = "$clientSeed-$nrand-$nonce";

$result = getProvablyFairResult($stringToHash, $unhashedServerSeed, $ticketQuantity);

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 87,664 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.

Did this answer your question?