SHA-256: how the hash behind provably fair games works
How SHA-256 turns any input into a 64-character digest, how MD5 and SHA-1 broke, and what a hash commitment can and can't hide.
Fact-checked 30 October 2026 · 8 sourcesSHA-256 sits under every provably fair check on this blog: the server seed commitment you see before betting, each link of a crash or roulette hash chain, and the HMAC that turns seeds into results. Those checks are only as strong as the hash. Below is what SHA-256 does to an input, how the older MD5 and SHA-1 broke, and the one thing no hash can hide.
What SHA-256 does
SHA-256 takes any input shorter than 2⁶⁴ bits and returns 256 bits, usually written as 64 hexadecimal characters. It has no key, so anyone who hashes the same input gets the same output, called the digest. NIST's standard says digests "are used to detect whether messages have been changed since the digests were generated".
Change or add a single character and about half of the 256 bits flip, as if a new digest had been picked at random. Here is the digest of dust2 next to four near-misses, computed for this article:
| Input | Digest starts with | Bits that differ from dust2 (of 256) |
|---|---|---|
dust2 | 86f50002b43d2c42 | 0 |
dust3 | b61dbcaa14af947d | 122 |
Dust2 | abc113ff4deab66e | 134 |
dust2 plus a space | 52055ff02e91b2ae | 134 |
dust2 plus a newline | 519c404953b2440a | 128 |
Unrelated 256-bit values differ in 128 bits on average, give or take 8, so these near-misses are no closer to the original than random digests. A nearly right guess gets no hint that it was close.
Where it came from and what happens inside
SHA-256 is part of the SHA-2 family, designed by the US National Security Agency and published by NIST as a draft in 2001, then as a standard, FIPS 180-2, in August 2002. The current text is FIPS 180-4 from August 2015; NIST decided in 2023 to revise it and drop SHA-1.
Inside, the input is padded to a multiple of 512 bits: a 1 bit, then zeros, then its length as a 64-bit number. Each 512-bit block is mixed into a state of eight 32-bit words over 64 steps of additions, rotations, shifts and bitwise logic, and the state after the last block is the digest. The input abc fits in one block; a 64-character seed is already 512 bits, so it needs two.
The 64 step constants come from the cube roots of the first 64 primes, and the starting state from the square roots of the first eight. Recomputed in Node.js for this article, all 72 values match RFC 6234.
Three properties, and the one a commitment leans on
NIST rates SHA-256 against three kinds of attack. A strength of n bits means an attack takes on the order of 2ⁿ operations.
| Property | The attacker's task | NIST strength | In a seed commitment |
|---|---|---|---|
| Preimage resistance | Find an input for a given digest | 256 bits | Players can't recover the hidden server seed |
| Second preimage resistance | Find another input with a given input's digest | Up to 256 bits | An honestly made seed can't be swapped later |
| Collision resistance | Find any two inputs with the same digest | 128 bits | The house can't prepare two seeds behind one hash |
For players, the last row matters most. If the house could find two seeds with the same digest, it could publish that digest and later reveal whichever seed did better against your client seed.
Collisions are cheaper to find than preimages because of the birthday paradox. In a room of 23 people, two share a birthday 50.7% of the time, because there are 253 pairs, not just the 22 that include you. After 2¹²⁸ random digests the chance that two match is about 39%, which is why 256 output bits give 128 bits of collision strength. At 10¹⁸ hashes a second, that many hashes would take about 11 trillion years.
How MD5 and SHA-1 broke, and where SHA-256 stands
MD5, from 1992, has a 128-bit digest; its first collisions were published in 2004. A 2007 study reported finding one in 10 seconds or less on a 2.6 GHz Pentium 4, and until the end of 2008 MD5 collisions could be used to forge web certificates that widely used browsers would accept. Its preimages held up far better: in 2011 the best preimage attack still needed about 2¹²³ steps.
SHA-1, from 1995, has a 160-bit digest. NIST deprecated it in 2011 after a 2005 attack on its collision resistance, and on 23 February 2017 CWI Amsterdam and Google announced the first actual collision: two different PDF files with the same hash. It took 9,223,372,036,854,775,808 SHA-1 computations, exactly 2⁶³, which Google put at 6,500 years of CPU time and 110 years of GPU time.
Nobody has published a collision for full SHA-256. Attacks reach only cut-down versions: a 2026 paper on the IACR ePrint archive gave the first colliding pair for 36 of the 64 steps, and a theoretical attack on 38 needing about 2¹⁰⁴ operations. NIST still rates SHA-256's collision strength at 128 bits, and 2¹²⁸ is about 3.7 × 10¹⁹ times the SHA-1 collision's 2⁶³.
Why bets use HMAC, not a plain hash
Because the digest is simply the state after the last block, a plain hash of a secret followed by a message can be extended. Anyone with the digest and the input's length can resume hashing and get a valid digest for the secret, the message, its padding and extra text of their choosing, without seeing the secret. This is length extension, and MD5 and SHA-256 are both open to it.
In September 2009 Thai Duong and Juliano Rizzo showed that Flickr's API, which signed requests as MD5(secret ‖ arguments), was open to it: given one signed request, anyone could sign longer ones without the secret. Their advisory recommended HMAC instead.
HMAC hashes twice, with the key mixed into both passes. Only a hash of the inner pass, the one that reads the message, is ever published, so the state needed to extend the message never appears.
Solo games on cs2.casino use it this way: block k = HMAC-SHA256(server seed, "client seed:nonce:k"), with the server seed committed by its SHA-256 hash before you bet. The provably fair explainer shows how those blocks become floats and results.
What a hash can't hide
Preimage resistance only protects an input that can't be guessed. If a site committed to a dice roll itself, a number from 0.00 to 99.99, there would be only 10,000 inputs to try. In tests for this article, Node.js on a two-core cloud server tried them all and found the committed roll in 25 milliseconds or less.
Weak passwords fall the same way. A seed of 32 random bytes, by contrast, has 2²⁵⁶ possible values, and trying them all at 10¹⁸ guesses a second would take about 3.7 × 10⁵¹ years.
A commitment also says nothing about how the seed was generated, only that it didn't change after you saw its hash. The explainer covers that and other limits under what provably fair does not prove.
Checking a tool before you rely on it
Before checking a real bet, test your tool on published values. RFC 6234 gives the digest of abc, and Wikipedia's SHA-2 article gives the digest of empty input:
abc:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad- empty input:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Each of these printed the abc value in a test for this article (OpenSSL adds a label in front):
printf '%s' abc | sha256sumprintf '%s' abc | shasum -a 256printf '%s' abc | openssl dgst -sha256node -e "console.log(require('crypto').createHash('sha256').update('abc').digest('hex'))"
If your own input gives an unexpected digest, check for a stray newline first: echo dust2 | sha256sum prints the 519c4049… digest from the table, not 86f50002…. The step-by-step verification guide takes a made-up dice bet from seeds to roll.
A matching hash shows that a server seed didn't change after it was committed; it doesn't change what a game pays. Every game on cs2.casino shows its house edge and bet limits, and over time the house wins.
Sources
- FIPS 180-4, Secure Hash Standard (SHS) — NIST CSRC
- Hash Functions — NIST CSRC
- RFC 6234: US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF) — RFC Editor
- SHA-2 — Wikipedia
- RFC 6151: Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms — RFC Editor
- Announcing the first SHA1 collision (2017) — Google Online Security Blog
- Pushing Collision Attacks on SHA-2 to 39 Steps (2026) — IACR Cryptology ePrint Archive
- Flickr's API Signature Forgery Vulnerability (2009) — Thai Duong's blog


