Fair play, in the open

How the dice stay fair.

A quick look under the hood. None of this is required reading. The short version is simple: no one can touch the dice, and you can check it for yourself. Here is how that works.

The whole idea in one line: the dice are locked in before the game starts, and the proof is handed to you when it ends. This is called commit and reveal.

Four steps, start to finish

Every game runs the same four steps. The first two happen before you make a single move.

1. A secret key

At the start of each game the server rolls a fresh, random secret: a 256-bit key. It is never reused, and for now it stays hidden.

key = a random 64-character secret

2. A public stamp

The server publishes a fingerprint of that key: its SHA-256 hash. You cannot work backward from a fingerprint to the key, and the key cannot be changed without changing the fingerprint.

stamp = SHA-256(key)

3. Every roll is derived

Each roll is computed from the key and the roll number, so it was already decided the moment the game began. The same roll number always gives the same dice, for you and your opponent.

dice = from HMAC(key, roll number)

4. The reveal

When the game ends, the key is published. Re-hash it: if the fingerprint matches, the key was never swapped. Re-derive the rolls: they all match too. Done.

check = SHA-256(key) == stamp ?

See it happen

This runs right here in your browser, the same way your phone checks a real game. Roll a few times, then reveal the key and watch the fingerprint line up.

public stamp =
secret key = hidden until you reveal
Roll to see each die derived from the sealed key…
Nothing to verify yet. Roll, then reveal.

The exact rule, for the curious

If you like the details: this is precisely how a die value comes out of the key. It is written so every face from 1 to 6 is equally likely, with no bias.

# for roll number n, take the bytes of: HMAC-SHA256(key, "n:counter") # each byte b below 252 gives one die: die = 1 + (b mod 6) # 252 = 42 x 6, so 0..251 splits evenly into 1..6 # the rare byte 252..255 is skipped, so every face stays fair

The very same code runs on the game server and on your phone, character for character. Neither one can quietly change a roll, because the other would notice. You never have to take our word for it.

That is the whole trick.

Sealed before you play, revealed when it ends, fair the whole way through. Now go win one on merit.

Play soon on iOS & Android   Back to home