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

1

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.

2

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.

3

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.

4

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.

Security Guarantee

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
}