Provably Fair System
Every case opening is cryptographically verifiable. No trust required. The server seed is hashed before your roll and only revealed afterward โ making pre-determination impossible.
How It Works
Server Seed (Hidden)
The server generates a fresh 256-bit random seed for each open and stores it in the database. Only its SHA-256 hash is shown to you beforehand as a commitment โ the raw seed stays in the DB until you request a reveal after the roll.
Client Seed + Client Salt + UUID + Nonce
You supply a client seed (rotatable any time). The server adds two tamper-proof components: a client salt (server-generated per-user, never sent to you) and your Supabase UUID with dashes stripped. Together these prevent seed-grinding attacks where a user knows both seeds and tries to pre-compute outcomes.
HMAC-SHA256 Roll
The server computes HMAC-SHA256(serverSeed, clientSeed:clientSalt:uuid:nonce). The first 8 hex chars become a 32-bit integer taken mod 10,000 โ a roll between 0 and 9,999. The full HMAC message is shown on your receipt so you can reproduce it.
Card Mapping + DB Reveal
The roll selects a card via cumulative weighted odds. After the result, click "Reveal Server Seed" โ the server fetches the seed from the database, verifies its SHA-256 matches the pre-roll commitment, and returns it. You can then reproduce the exact roll independently.
The raw server seed is never sent to the client before the roll. All seed generation and roll computation happens in a server-side API endpoint. The client receives only: the SHA-256 hash of the server seed (pre-roll commitment), the roll result, and an opaque reveal token redeemable after the round settles.
Your Current Seeds
Your client seed and nonce are stored server-side and shown in the Seed Settings panel on each case page. Change your client seed there โ doing so resets the nonce to 0 and starts a new verifiable session. The server seed hash (your next session's commitment) is also shown in that panel.
Go to Cases โVerify a Roll
After revealing your server seed from the History page, paste all values here to independently reproduce the result.
Algorithm Reference
// Reproducible in any browser โ no libraries needed
async function verify(serverSeed, clientSeed, clientSalt, userId, nonce) {
const key = new TextEncoder().encode(serverSeed);
const msg = new TextEncoder().encode(`${clientSeed}:${nonce}`);
const k = await crypto.subtle.importKey(
'raw', key, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
);
const sig = await crypto.subtle.sign('HMAC', k, msg);
const hex = [...new Uint8Array(sig)]
.map(b => b.toString(16).padStart(2, '0')).join('');
return parseInt(hex.slice(0, 8), 16) % 10000; // 0โ9999
}