What is Provably Fair?
Provably fair is a cryptographic verification system that allows players to verify that game outcomes are not manipulated. Using a combination of server seeds, client seeds, and nonces, the system generates verifiable random numbers that determine case opening results.Every case opening in Cajas is provably fair - you can verify that the server couldn’t have manipulated the outcome.
Core Concepts
Server Seed
Random value generated by the server, kept secret until after the game
Client Seed
Random value chosen by the player (or auto-generated)
Nonce
Sequential counter incremented with each game
How It Works
Seed Initialization
When a user first plays, the system generates:
- Server Seed: 64 random hex characters (256 bits)
- Client Seed: 32 random hex characters (128 bits)
- Nonce: Starts at 0
Hashed Server Seed
The server seed is hashed with SHA-256 and shown to the player before any game. This proves the server committed to a value before the outcome.
Calculate Outcome
When opening a case:
- Increment nonce by 1
- Combine:
HMAC-SHA256(serverSeed, clientSeed + "-" + nonce) - Convert to decimal between 0 and 1
- Map to item based on probabilities
Implementation
Seed Generation
The system uses Node.js crypto module for cryptographically secure randomness:lib/provably-fair.ts
Server seeds use 32 bytes (256 bits) to match SHA-256’s security level. Client seeds use 16 bytes (128 bits) as they’re chosen by players.
Roll Calculation
The core algorithm that determines outcomes:lib/provably-fair.ts
Why HMAC instead of simple hash?
Why HMAC instead of simple hash?
HMAC (Hash-based Message Authentication Code) is used because:
- Key separation: Server seed acts as a secret key
- Prevents manipulation: Client can’t reverse-engineer server seed
- Industry standard: Same approach used by Stake.com, CSGORoll, etc.
Winner Selection
Convert the 0-1 roll value to an actual item:lib/provably-fair.ts
Database Schema
User Seeds Table
Each user has one active seed pair:Game Rolls Audit Log
Every game is recorded for verification:API Endpoints
Get Current Seeds
Retrieve the user’s current seeds (with server seed hashed):Rotate Seeds
Generate new seeds (usually after revealing old server seed):Case Opening with Fairness Data
Opening a case returns fairness proof:app/api/cases/open/route.ts
Verification Example
How a player would verify a game:Security Properties
Pre-commitment
Pre-commitment
Server shows SHA-256 hash of server seed before any client input. This proves the server committed to a value before knowing the outcome.
Client Influence
Client Influence
Player can set their own client seed, ensuring they contributed to the randomness. Server cannot predict the outcome without knowing client’s seed.
Deterministic
Deterministic
Same inputs always produce same output. This means outcomes can be verified after revealing the server seed.
Cryptographically Secure
Cryptographically Secure
HMAC-SHA256 is a well-studied algorithm. Breaking it would require finding SHA-256 collisions, considered computationally infeasible.
Best Practices
Recommended Flow:
- Show server_seed_hash to player
- Player (optionally) sets custom client_seed
- Play games, incrementing nonce each time
- When player wants to verify, reveal the server_seed
- Rotate to new server_seed for future games
Nonce Incrementing
The nonce prevents reusing the same random value:Future Enhancements
Seed History
UI to view past server seeds and verify old games
Custom Client Seeds
Allow players to set their own client seed before playing
Automatic Rotation
Auto-rotate server seed every N games or time period
Verification Page
Built-in calculator to verify outcomes without code
Learn More
Case Opening
See how provably fair integrates with case opening
Industry Standards
Read about provably fair algorithms on Wikipedia
