Spinness uses crypto.getRandomValues() — not Math.random() — for every tool where fairness matters.
This is the same cryptographic random source browsers use to generate security keys and TLS sessions.
The tools below explain exactly when each method is applied and why.
Two sources of randomness
Not all randomness is equal. Spinness uses two different methods depending on what a tool actually needs — and every tool page documents which one it uses.
crypto.getRandomValues — cryptographically secure
crypto.getRandomValues() is provided by the browser's Web Crypto API.
It draws entropy from the operating system's secure random source —
/dev/urandom on Linux, CryptGenRandom on Windows.
The results are statistically unpredictable and suitable for security-sensitive uses.
When we use it: Wheel of Names spins, coin flips, team generator
draws, any tool where perceived fairness matters. If a tool claims a result is
"fair" or "unbiased," it uses crypto.getRandomValues.
Math.random — pseudorandom
Math.random() is JavaScript's built-in pseudorandom number generator.
It produces a deterministic sequence from an internal seed state. The output is
statistically well-distributed and indistinguishable from random for most purposes —
but it is not cryptographically secure.
When we use it: Entertainment tools where security is irrelevant — random color generation, random word shuffling, visual animations. We document which method each specific tool uses on its own page.
Uniform distribution
Raw values from both sources are mapped to a target range using rejection sampling rather than the naive modulo approach. Modulo introduces a slight bias toward lower values when the range does not divide evenly into the output space. Rejection sampling discards out-of-range outputs and draws again until a value falls cleanly within the target, which eliminates the bias entirely.
Source code
All randomness logic lives in src/lib/random/. The functions are:
randomInt(max), randomIntRange(min, max),
pickOne(array), pickMany(array, n), and
shuffle(array). Each uses crypto.getRandomValues as
the entropy source. Math.random is used only where explicitly noted in tool code.
Standards and references
The cryptographic random number generation used by Spinness follows the principles defined in NIST Special Publication 800-90A Rev.1 (Recommendation for Random Number Generation Using Deterministic Random Bit Generators). The browser's crypto.getRandomValues() API is documented on MDN Web Docs: Crypto.getRandomValues().
For a deeper understanding of why cryptographically secure randomness matters for fairness-sensitive applications, see the NIST standards above. The key property — computational indistinguishability from true randomness — is what separates crypto.getRandomValues() from Math.random() in security-relevant contexts.
How to verify statistical randomness: NIST SP 800-22
NIST Special Publication 800-22 Rev.1a defines 15 statistical tests for evaluating whether a sequence of bits appears random — tests for frequency, block frequency, runs, longest-run-of-ones, serial, and others. These tests are used to validate that a PRNG does not produce detectable patterns.
The OS-level entropy sources that back crypto.getRandomValues() are designed to pass all 15 NIST SP 800-22 tests. Math.random(), by contrast, is not required to pass these tests and browser implementations vary. This is the practical difference between the two sources: one is validated against a published cryptographic standard, one is not.
Frequently asked questions
Is crypto.getRandomValues truly unpredictable?
"Unpredictable" is the right word — "truly random" is philosophically harder to pin down. crypto.getRandomValues draws entropy from the operating system, which mixes hardware events, disk activity, network timing jitter, and other noise into its seed state. A determined adversary with full knowledge of the algorithm still cannot predict the next output because the seed is hidden and constantly changing. That is what "cryptographically secure" means in practice, and it is the same source applications use to generate cryptographic keys.
Can I use Spinness results for official draws and giveaways?
Yes. Tools that use crypto.getRandomValues — the Wheel of Names, Team Generator, Coin Flip, and others — produce results that are statistically indistinguishable from true random. For formal public giveaways, we recommend screenshotting the result or recording your screen so you have an audit trail if anyone asks how the winner was picked. The randomness itself is not the weak link; documentation is.
Why use Math.random at all if crypto is better?
For visual and entertainment tools — random color generation, word shuffling, animation — calling crypto.getRandomValues for every frame adds overhead with no real benefit. Cryptographic security matters when fairness is the whole point (draws, coin flips, raffle wheels). For "what random hex color should I try," Math.random is faster and equally correct for the use case. Each tool page documents which source it uses.
What is rejection sampling and why does it matter for fairness?
Here is the problem it solves: if you take a large random number and map it to a small range using modulo, the lower values in the target range appear slightly more often because the large range rarely divides evenly. The bias is small — a fraction of a percent — but for a draw where fairness matters, that is enough to make the result technically unfair. Rejection sampling discards any output that falls in the "overflow" zone and draws again, keeping every outcome equally likely regardless of range size.