Type "random picker" into a search engine and you'll find hundreds of them. Almost all of them share the same quiet flaw: they aren't actually random. They're pseudo-random — built on Math.random(), a fast, predictable algorithm that was never designed to resist bias or manipulation. For picking a background color, that's fine. For picking a raffle winner, a classroom volunteer, or a contest winner in front of a skeptical audience, it's a problem.
SoChoosey doesn't use Math.random() anywhere in its code — not once, in any of the seven animations. This post explains exactly what it uses instead, why it matters, and how you can independently verify that any given result was fair, without needing to trust us at all.
Why Math.random() Isn't Good Enough
JavaScript's built-in Math.random() is a pseudo-random number generator (PRNG). It produces numbers that look random but are actually the output of a deterministic algorithm seeded from a starting value. Given the seed, every future value is predictable. Browsers don't expose the seed to attackers, so it's not a security hole for most uses — but it was never built for use cases where provable fairness matters, and it has no mechanism for proving after the fact that a result wasn't cherry-picked.
Where SoChoosey's Randomness Actually Comes From
SoChoosey uses crypto.getRandomValues() — a Web Crypto API method built into every modern browser. Unlike Math.random(), this function pulls from your operating system's cryptographically secure random number generator, which is itself seeded from hardware entropy: tiny, physically unpredictable variations like electrical noise, timing jitter, and mouse or touch input. It's the same underlying source of randomness used to generate TLS certificates and encryption keys — infrastructure that has to resist deliberate attack, not just look convincing.
Every random decision inside SoChoosey — which segment the wheel lands on, which ball rises to the top of the lottery tank, which face the die settles on — traces back to this single function. There is exactly one source of randomness in the entire app, and it's auditable in the code as SecureRandom.
The Modulo Bias Problem (and How Rejection Sampling Fixes It)
Getting a random number is only half the problem. The harder part is turning that number into a fair index within your list — and this is where most homemade random pickers quietly introduce bias without realizing it.
A naive approach takes a random number and applies the modulo operator: value % listLength. This looks fine, but it isn't. Since 2³² isn't evenly divisible by most list lengths, some remainders occur slightly more often than others — meaning some items in your list get a marginally higher chance of winning. For a list of 5, the bias is small but real. For certain list lengths, it's measurable enough to matter.
SoChoosey avoids this entirely using rejection sampling: it generates a random value, checks whether that value falls within an unbiased range for your list length, and — if it lands in the small biased "tail" region — simply throws it away and generates a new one. In practice this loop runs once, occasionally twice, and the result is a perfectly uniform distribution with no detectable skew toward any item, regardless of how many items are on your list.
The Prove It System: Committing Before the Spin
Rejection sampling solves the fairness math. It doesn't solve the trust problem — your audience still has to take your word that the spin wasn't repeated until it produced a convenient winner. That's what the Prove It feature is for, and it's built on a well-established cryptographic idea called a commit-reveal scheme.
Before the animation starts
SoChoosey generates 32 random bytes using SecureRandom.bytes(32), then computes their SHA-256 hash. This hash — the "commitment" — is mathematically derived from the secret bytes, but reveals nothing about them.
The winner is already decided
The winning index is derived directly from those same 32 bytes, using the same rejection-sampling technique described above. No second, separate random call happens later. The winner that the animation is about to reveal was fixed the instant the commitment was created — before a single frame of animation has played.
The animation plays normally
The wheel spins, the balls bounce, the die tumbles — all exactly as it looks. Nothing about the visual experience changes. The only difference is that the outcome was locked in cryptographically before it started.
After the reveal, anyone can check the math
Click "Verify this result" and SoChoosey shows you the 32-byte secret in hex, alongside the commitment hash. Hash the secret yourself with any SHA-256 tool and confirm it matches. If it matches, the winner could not have been chosen after the fact — full stop.
Why You Can't Fake a Match
SHA-256 is a one-way function: it's computationally infeasible to find two different inputs that produce the same output, and it's infeasible to reverse a hash back into its input. This is the same property that makes SHA-256 suitable for password storage and blockchain integrity checks. Applied here, it means: once a commitment hash has been generated and shown to you, there is no secret other than the original one that will ever hash to that value. If someone tried to swap in a different "winner" after the fact, the revealed secret simply wouldn't match the hash they already committed to — and anyone watching would catch it instantly.
How to Verify a Result Yourself
- Run a spin as normal and let the winner reveal.
- Click the "Verify this result" link that appears below the winner.
- Copy the revealed secret (32 bytes, shown as hex) using the copy button.
- Paste it into any SHA-256 calculator — the Verify panel links directly to one.
- Compare the output to the commitment hash shown in the same panel. They should match exactly.
This whole process takes under a minute, requires no technical background, and doesn't require trusting SoChoosey at any point — you're checking the math independently, in a tool we don't control.
Why This Level of Rigor Exists for a Free Spinner App
Most of the time, nobody will click "Verify." A teacher picking a student to answer a question doesn't need cryptographic proof. But the moments where it matters — a contested office raffle, a social media giveaway with thousands of entrants, a classroom discussion about how randomness actually works — are exactly the moments where "trust me" isn't good enough. We built the Prove It system so that the answer is never "trust me." It's "check for yourself."
If you want to see this in action, run any spin at sochoosey.app and open the Verify panel afterward. If you're the technical type, the underlying SecureRandom and prove-it logic is documented step by step in our source, with every mathematical step spelled out in comments.