ToolsGambling
TG
file-metadata.sys
SectionCasino
AuthorEvgeniy Volkov
PublishedApr 22, 2026
Read Time14m
DifficultyBeginner
Status
Verified
CategoryGuides
Provably Fair RNG Explained: Full Technical Guide (2026)

Provably Fair RNG Explained: Full Technical Guide (2026)

provably fair random number generationprovably fair rnghmac-sha256 rngcsprng provably fairchainlink vrf casinoprovably fair dice formulaprovably fair crash formulapf rng attack surface
> Contents

Provably Fair Random Number Generation Explained (2026)

You just placed a 0.5 BTC bet on a crypto dice game. The screen rolls 37.42 and you lose. You open the fairness panel and it shows a server seed hash, your client seed, and a nonce — four values that supposedly prove nothing was rigged. But how did those four values become 37.42? What actually turned random hex characters into a specific dice roll?

Here's the thing: the entire "provably fair" promise hinges on one specific act — converting cryptographic hash output into game outcomes. Miss how that conversion works and provably fair feels like magic marketing. Understand it and you can audit any PF casino in about 60 seconds, spot fake implementations on sight, and know exactly which attacks the protocol does and doesn't defeat.

This guide walks you through provably fair random number generation the way a developer would build one in 2026 — the CSPRNG primitives under the hood, the HMAC-SHA256 formula that turns seeds into numbers, the different mapping schemes for dice, crash, and cards, and the attack surface that survives even when the math is perfect. By the end you'll know why PF RNGs are cryptographically unbreakable, which implementation bugs still ruin them, and when blockchain randomness (Chainlink VRF) kicks in instead.

TL;DR — How PF RNGs Actually Generate Numbers

Every provably fair game uses the same core RNG primitive, only the output mapping changes. Here's the 60-second version.

StepWhat happensWho controls it
1. Generate server seedCasino's CSPRNG outputs a 32-64 byte random stringCasino
2. Hash and publishSHA-256(server_seed) is shown to you before the roundCasino
3. Collect client seed + nonceYour browser adds a client seed; nonce is the round counterYou + protocol
4. Compute HMAChex = HMAC-SHA256(server_seed, client_seed : nonce)Deterministic
5. Map hex to outcomeSlice + modulo + divide = dice roll, crash multiplier, or cardDeterministic
6. Reveal and verifyAfter rotation the raw seed is revealed; anyone can re-run step 4You

The math is:

outcome=f(HMAC-SHA256(server_seed,  client_seed:nonce))\text{outcome} = f\big(\text{HMAC-SHA256}(\text{server\_seed},\; \text{client\_seed} : \text{nonce})\big)

Where f is a game-specific mapping function — f_dice returns 0-99.99, f_crash returns a multiplier, f_cards returns shuffled deck positions. The HMAC part is identical across every PF casino in the world.

Key Numbers You Need to Know

  • 3 inputs: server seed + client seed + nonce produce every outcome
  • 64 hex chars: length of a SHA-256 / HMAC-SHA256 output
  • 128 hex chars: length of HMAC-SHA512 (used by BC.Game and PF blackjack)
  • ~2^256 operations: what it would take to break HMAC-SHA256 — astronomically out of reach
  • 0.00-99.99: standard dice range after mapping
  • 1.00x to ∞: standard crash multiplier range (bounded in practice by float precision)

Fair ≠ Profitable

The RNG being provably fair tells you the casino couldn't manipulate the outcome after you bet. It does not tell you:

  • Whether the house edge is reasonable (check RTP separately)
  • Whether the casino will honor withdrawals
  • Whether bonuses and wagering terms are honest
  • Whether the server seed pool was unbiased before it was committed

We'll cover the full attack surface below. For a broader comparison with traditional certification, see our provably fair vs RNG certified guide.

What Makes an RNG "Provably Fair"

Before we get to the formula, it helps to separate provably fair from the broader RNG world. PF is a specific upgrade to CSPRNGs, not a replacement.

The Commit-Reveal Primitive

The whole trick behind provably fair is a cryptographic pattern called commit-reveal.

Before the round starts, the casino commits to a specific server seed by publishing its SHA-256 hash. The hash is a 64-character fingerprint that uniquely identifies the seed without revealing it. Because SHA-256 has no practical collision attacks, the casino can't later find a different seed that produces the same hash — they're locked in.

After the round (or after you rotate seeds), the raw server seed is revealed. You hash it yourself. If your computed hash matches what was published before the round, the casino proved they didn't swap seeds mid-round. Combined with your client seed (which they didn't know in advance), this makes per-round outcome manipulation cryptographically impossible.

The commit-reveal layer is what separates PF from any other CSPRNG. A traditional RNG-certified casino also uses a CSPRNG — but nothing stops them from swapping it out in production, as iTech Labs audits only prove statistical properties, not runtime identity.

HMAC as the RNG Primitive

HMAC-SHA256 is the actual random number generator inside every PF round. Here's why it works:

  • Deterministic: Given the same inputs, HMAC always produces the same output. This is what lets you verify.
  • One-way: Given the output, you can't recover the server seed (the key). This is what keeps the outcome unpredictable.
  • Uniform: HMAC outputs are indistinguishable from random 256-bit strings. This is what keeps the game unbiased.
  • Keyed: The server seed acts as a secret that must be known to reproduce the output. This is what prevents tampering.

Technically, HMAC-SHA256 isn't a CSPRNG by itself — it's a message authentication code. But when the key (server seed) is generated from a real entropy source, the construction is equivalent to a CSPRNG for all practical purposes. NIST formalized this as HMAC_DRBG in SP 800-90A Rev 1, and PF casinos essentially reimplement that standard with the addition of public seed commitment.

Why CSPRNGs Matter (Not Math.random)

Every legitimate PF casino generates its server seed with a cryptographically secure RNG — not JavaScript's Math.random(). The difference matters more than most players realize:

GeneratorPredictable after seeing output?Acceptable for PF?
Math.random() (V8 in Chrome)Yes, after ~700 outputsNever
Linux /dev/urandomNoYes
crypto.getRandomValues (browser)NoYes
Node.js crypto.randomBytesNoYes
Hardware RNG (Intel RDRAND)NoYes

If a casino secretly seeds its server with Math.random(), a sophisticated attacker could reconstruct the seed from enough public outputs and predict every future round — even if the HMAC math is flawless. This is why checking your casino actually uses crypto.randomBytes or equivalent matters; the what is provably fair gambling explainer covers the full chain of trust.

How the Number Is Actually Generated

Now the actual formula. This is the section to bookmark — everything above was context.

Three Inputs, One Formula

Every provably fair round computes:

hex_output=HMAC-SHA256(server_seed,  client_seed  :  nonce)\text{hex\_output} = \text{HMAC-SHA256}(\text{server\_seed},\; \text{client\_seed} \; : \; \text{nonce})

In pseudocode:

function pfHmac(serverSeed, clientSeed, nonce) {
  const message = clientSeed + ':' + nonce
  const hex = hmacSha256(serverSeed, message)  // 64-char hex string
  return hex
}

The : colon is the canonical separator on Stake, Primedice, Rainbet, and most PF casinos. A few (BC.Game, Roobet) use different delimiters — always check the casino's fairness docs for the exact format.

The output is a 64-character hexadecimal string like 8b2d4a1f9c6e7b3d5a8f2c9e4b1d7a6f3e8c5b2d9a4f7e1c8b3d6a2f9e5c4b7d. That hex is the raw randomness — 256 bits of unpredictability, statistically indistinguishable from flipping 256 fair coins.

Verification Transparency: Aviator vs Other Methods

How verifiable is each method? Lime = high transparency (75+), yellow = medium (40–74), red = low/none (under 40). Provably fair Aviator lets you verify every single crash.

Loading chart...
High (75+)
Medium (40–74)
Low (under 40)

Scores reflect the degree to which individual game outcomes can be independently verified by the player.

Step-by-Step: From HMAC Output to Dice Roll

Let's do one round end-to-end.

Given values:

  • server_seed = f4a9c2e1b7d8e3c5a1b9f6d2e8c4a7b3e9d1c6a2b5f8e4c7a3b6e1d9c2a5b8f4
  • client_seed = player-xyz-42
  • nonce = 7

Step 1 — Compute HMAC:

HMAC-SHA256(server_seed, "player-xyz-42:7")
= 8b2d4a1f9c6e7b3d5a8f2c9e4b1d7a6f3e8c5b2d9a4f7e1c8b3d6a2f9e5c4b7d

Step 2 — Slice first 5 hex characters:

8b2d4 → convert to decimal → 569,300

Step 3 — Map to 0-99.9999:

dice = (569_300 % 1_000_000) / 10_000
     = 569_300 / 10_000
     = 56.93

Step 4 — Apply bet logic:

If you bet "roll under 50" → you lose (56.93 > 50). If you bet "roll under 60" → you win. The exact roll was determined the instant those three inputs combined, before any UI animation ran.

Step 5 — Verify:

Post-round, you receive the revealed server_seed. You hash it — SHA-256 matches the pre-committed hash? Good. You re-run steps 1-3 — reproduced 56.93? Good. The round is cryptographically proven fair.

For a full walkthrough with copy-paste values and screenshots, see how to verify a provably fair round.

Different Games, Different Mappings

The HMAC call is always identical. What changes is step 3 — how the hex gets mapped to a specific game outcome.

GameHex sliceFormulaOutput range
DiceFirst 5 chars(int % 1e6) / 1e40.0000-99.9999
CrashFirst 8 charsfloor((100 * 2^52 - h) / (2^52 - h)) / 1001.00x to very high
CoinflipFirst 2 charsint % 2 (0 or 1)Heads/Tails
RouletteFirst 2 charsint % 37 (Euro) or % 38 (Am)0-36 or 0-37
PlinkoFirst 4 chars × n dropsint % rows per dropPath through pegs
Blackjack (HMAC-SHA512)4 chars per cardint % 52 with replacement logicCard deck position

Each mapping is designed to be uniform across its output range — modular arithmetic on a uniformly random hex value preserves uniformity. This is why PF games can claim honest RTP without the casino manipulating individual rounds. It's the mapping formula that gets tuned to hit the casino's target house edge, not the random number itself.

From Hex String to Game Outcome (With Math)

The dice mapping is worth dissecting because it's the clearest case — and because it shows why provably fair dice distributions are genuinely uniform when implemented correctly.

Dice Mapping (0-99.9999)

Stake's dice uses the first 5 hex characters, which gives 20 bits = 1,048,576 possible values. The mapping is:

dice=(int(hex0:5)  mod  106)104\text{dice} = \frac{(\text{int}(\text{hex}_{0:5}) \; \text{mod} \; 10^6)}{10^4}

Why modulo 1,000,000 when the slice can reach 1,048,575? Because without the modulo, values 1,000,000-1,048,575 would map to 100.0000-104.8575, outside the dice range. Modulo folds those back — but introduces a tiny bias (values 0-48,575 are more likely than 48,576-99,999 by a factor of 2/1). To eliminate the bias, real implementations reject slices above 1,000,000 and advance to the next hex chunk (chars 5-10, then 10-15, etc.).

Done correctly, this produces a perfectly uniform distribution across 0.0000-99.9999. A 10,000-roll test shows essentially flat coverage — the histogram below reproduces what you'd see with any legitimate PF dice implementation.

10,000 PF Dice Rolls — Distribution Across Buckets

Each bucket covers a 10-point slice of the 0-99.99 dice range. Expected count per bucket is 1000. Observed counts cluster within ±3% — statistically indistinguishable from uniform randomness. Generated by running HMAC-SHA256 10,000 times with sequential nonces.

Loading chart...
Samples
10,000
Mean
49.97
Std Dev
28.85
χ² (10 bins)
2.58

χ² critical value for uniform distribution at 9 degrees of freedom (p=0.05) is 16.92. Observed 2.58 is well below threshold — no detectable bias. Numbers generated via Web Crypto API HMAC-SHA256.

Crash Mapping (Multiplier)

Crash is more interesting because the output isn't uniform — it's deliberately skewed to create dramatic gameplay while preserving a target house edge.

crash=100252h252h100\text{crash} = \frac{\left\lfloor \dfrac{100 \cdot 2^{52} - h}{2^{52} - h} \right\rfloor}{100}

Where h = int(hex[0:8]) (a 32-bit integer from the first 8 hex chars). With one modification: if h mod 33 == 0, the multiplier is 1.00x (instant bust), which creates Stake's ~1% house edge. Other casinos use different divisors — 25 (Rainbet ~4% edge), 50 (low-edge variants), 100 (very low-edge).

Run this formula a million times and you get a distribution where ~50% of rounds bust under 2x, ~10% pass 10x, and maybe 1% reach 100x. The expected value works out to 0.99 per 1 bet — the missing 1% is the house edge baked into the formula's constants, not into any per-round manipulation.

Card Mapping (Deck Shuffles)

PF blackjack, poker, and baccarat shuffle virtual decks using HMAC-SHA512 (longer output = more cards per hash call). The Fisher-Yates shuffle is the standard:

for i = 51 down to 1:
  j = hmac_int(i) mod (i + 1)
  swap(deck[i], deck[j])

Each hmac_int(i) call consumes 4 hex chars of the 128-char SHA-512 output. One round's cards are fully determined by one HMAC call, which is why you often see PF blackjack games show 13+ decimal-converted integers in the verification panel — one per card swap. For the specific implementation on Stake and BC.Game, see the provably fair blackjack guide.

Traditional RNG vs Provably Fair RNG

At the RNG level specifically (not the broader fairness stack), PF is a strict superset of certified CSPRNG.

Where Traditional RNGs Fall Short

Certified RNGs from eCOGRA, iTech Labs, and GLI are all cryptographically secure — the math is as strong as PF's. The problem isn't the primitive, it's the runtime trust model:

  • The certified RNG lives on the casino's server, audited once
  • You never see its output directly, only the game's end state
  • Nothing forces the casino to keep running the certified code in production
  • A per-round dispute can't be resolved in real time

If Pragmatic Play's certified slot engine quietly runs a different RNG in Roobet's production than the one eCOGRA tested, no amount of certificate checking catches it. The gap closes only with open verification per round.

What PF Adds to the Primitive

Provably fair takes the same cryptographic foundation and exposes it. Specifically:

  • The server seed hash is published before your bet (commitment)
  • Your client seed contributes to the HMAC input (co-signing)
  • The raw server seed is revealed after the round (reveal)
  • The computation is deterministic and reproducible in any browser (verification)

That's the whole difference. Same HMAC, same CSPRNG math — with four extra steps of transparency layered on top. For a deeper walkthrough of how both models stack up, see provably fair vs RNG certified.

PF RNG covers centralized crypto casinos nicely. But what about fully decentralized applications — onchain lotteries, NFT trait assignment, onchain dice? That's where a different solution takes over.

Why Blockchains Can't Generate Secure Random Numbers

Every blockchain is deterministic by design — every validator must produce the same state from the same inputs, or consensus breaks. That makes randomness structurally hard:

  • block.timestamp is miner-controllable within a few seconds
  • block.blockhash can be manipulated by miners withholding blocks
  • block.prevrandao (post-Merge Ethereum) is better but still biasable by validators
  • Any onchain entropy source can be read by the contract before it's used, defeating the purpose

Naive dApp lotteries that used blockhash have been drained in the past. The economic incentive to manipulate a $1M jackpot can make a miner rationally withhold a block.

Chainlink VRF (Verifiable Random Function) generates randomness offchain and delivers it onchain with a cryptographic proof. The flow:

  1. Smart contract requests a random number
  2. Chainlink oracle generates the value offchain using its private key + request seed
  3. The proof is a BLS signature that anyone can verify against the oracle's public key
  4. Both the value and the proof are posted back onchain in a single transaction
  5. The contract verifies the proof before using the value

The critical property: because the proof ties the random value to the oracle's private key and the request seed, the oracle cannot cherry-pick convenient values. Any deviation is mathematically detectable.

When to Use VRF vs HMAC-Based PF

Use caseBest fitWhy
Centralized dice/crashHMAC-based PFSimpler, cheaper, same guarantees
Onchain lotteryChainlink VRFTrustless, no central operator
NFT trait assignmentChainlink VRFNon-manipulable rarity
Centralized blackjackHMAC-based PFChainlink VRF too expensive per card
DeFi game with high jackpotChainlink VRFMiner manipulation risk too high

Most crypto casinos in 2026 still use HMAC-based PF because it's fast, cheap, and already well-understood. VRF is where onchain DeFi, NFTs, and fully decentralized gaming shine. Our provably fair Bitcoin games ranking filters specifically by which PF implementation each casino uses.

Attack Surface of PF RNGs

A cryptographically perfect PF RNG can still be broken by bad implementation. Here's what survives the math.

Biased Seed Pool Attack

The most realistic attack — and one reason client seed rotation matters.

A dishonest casino generates thousands of candidate server seeds in advance. For each, they compute outcomes against common client seed patterns (default browser formats, frequent words). They deploy only seeds that happen to produce more losses than wins against predictable client seeds.

Every deployed seed still hashes correctly to its pre-committed hash. The commit-reveal math passes. But the pool of available seeds was cherry-picked before any player saw them, and the long-run house edge quietly exceeds the stated RTP.

Why Rotation Defeats It

Biased-seed attacks require the casino to know your future client seed before committing the server seed. Rotate your client seed every 50-100 bets and the casino's pre-computation becomes useless — they committed to a server seed before knowing the new client seed, so they can't steer outcomes.

This is why legitimate casinos let you rotate instantly. A PF casino that refuses client seed rotation (or auto-regenerates the client seed on their schedule, not yours) is signaling the attack surface is open. The client seed vs server seed guide covers the full rotation workflow.

Weak Entropy Sources

If the server seed generation uses predictable entropy, the commit-reveal protocol still runs but the attacker can predict seeds.

The Math.random Trap

JavaScript's Math.random() is a linear congruential generator variant. After observing ~700 consecutive outputs, an attacker can reconstruct the full internal state and predict every subsequent output. If a PF casino uses Math.random for server seed generation:

  1. Attacker plays 700+ rounds, collecting each revealed server seed
  2. Attacker reconstructs the PRNG state
  3. Attacker predicts the next hashed server seed before it's committed
  4. Attacker bets with full knowledge of the outcome

Prevention: casinos must use crypto.randomBytes(32) (Node.js), crypto.getRandomValues(new Uint8Array(32)) (browser), or hardware RNG. The difference is one line of code but the security gap is total.

Implementation Red Flags

Short checklist of signals that a PF RNG isn't safe:

  • No client seed rotation button, or rotation takes >5 seconds
  • Client seed is auto-regenerated by the casino on their schedule
  • Server seed history doesn't show the algorithm or slice width
  • Verification tool only works on the casino's own website (not locally)
  • No published hash algorithm — "SHA-256 somewhere" isn't enough; you need the exact formula
  • Revealed server seeds don't match their pre-committed hashes in any round

Any one of these suggests the PF claim is marketing varnish on top of a regular RNG. For a side-by-side on which casinos actually publish their PF code, see the provably fair Bitcoin games ranking.

Try It Yourself — Interactive Verifier

The math stops being abstract the moment you run it on your own seeds. Paste any four values from your casino's fairness panel into the verifier below — everything executes in your browser via the Web Crypto API, no data is sent to our server.

A practical tip: if you don't have a real PF casino bet handy, try these throwaway test values to see a verified round:

  • Server seed hash: bf3c0a9b0f4b3c8e8f4f0c5f0c4e8b7d8f3e2a1c9f6e3b7c4d5a8e2f9b1c6d3a (example only — won't match real hashes)
  • Server seed: f4a9c2e1b7d8e3c5a1b9f6d2e8c4a7b3e9d1c6a2b5f8e4c7a3b6e1d9c2a5b8f4
  • Client seed: demo-player
  • Nonce: 1

The result shows a PASS / FAIL verdict on hash match plus the reconstructed dice and crash outcomes. The same logic runs behind the Aviator provably fair calculator for Spribe's crash-style game, and our full verifier at the provably fair hub covers every mainstream PF casino. For sizing bets against a known RTP once you've confirmed the RNG is legit, pair it with our RTP calculator, house edge calculator, and bankroll calculator.

FAQ

Frequently Asked Questions

author-credentials.sysE-E-A-T
Evgeniy Volkov

Evgeny Volkov

Verified Expert
Math & Software Engineer, iGaming Expert

Over 10 years developing software for the gaming industry. Advanced degree in Mathematics. Specializing in probability analysis, RNG algorithms, and mathematical gambling models.

Experience10+
SpecializationiGaming
Status
Active

Was this article helpful?

Share Article
launch-tools.sh

Ready to Calculate Smarter?

Use our free professional calculators to make data-driven decisions.