← Powrót do bloga

Czy Twój generator liczb losowych jest uczciwy? Praktyczna lista kontrolna audytu

Narzędzia i uczciwość30 marca 2026·7 min czytania
Random number generator fairness audit

Kiedy organizujesz loterię, losowo wybierasz drużyny lub przydzielasz zadania w drodze loterii, uczciwość nie jest opcjonalna — o to właśnie chodzi. Ale „losowe” nie oznacza automatycznie „uczciwe”. Ukryte błędy w generatorach liczb losowych (RNG) mogą zniekształcać wyniki w sposób niewidoczny, chyba że wiesz, gdzie szukać.

W tym artykule znajdziesz praktyczną listę kontrolną umożliwiającą audyt dowolnego RNG pod kątem uczciwości, niezależnie od tego, czy korzystasz z naszego Generatora liczb losowych, czy tworzysz własny.

Co oznacza uczciwość w losowaniach skierowanych do użytkownika

Uczciwy RNG daje wyniki, gdzie:

Pominięcie któregokolwiek z tych elementów podważa zaufanie, nawet jeśli wyniki „wyglądają” na losowe.

Typowe źródła uprzedzeń

Złe nasiona

A PRNG (generator liczb pseudolosowych) jest tak nieprzewidywalny, jak jego ziarno. Typowe złe nasiona:

Zawsze wysyłaj ze źródła kryptograficznego: crypto.getRandomValues() w przeglądarkach, /dev/urandom w systemie Linux lub crypto.randomBytes() w Node.js.

Odchylenie modulo

Drobny i powszechny błąd: użycie operatora modulo do redukcji liczby losowej do zakresu.

//BIASED — jeśli zakres RNG nie jest wielokrotnością 6,
// niektóre wyniki są nieco bardziej prawdopodobne
const roll = randomUint32() % 6; // POPRAWNE — próbkowanie odrzucone
funkcja fairDiceRoll() { const max = Math.floor(0xFFFFFFFF / 6) * 6; niech wartość; wykonaj { value = crypto.getRandomValues(new Uint32Array(1))[0]; } while (wartość >= max); zwracana wartość % 6;
}

W przypadku kości 6-ściennej odchylenie modulo w przypadku 32-bitowej liczby całkowitej wynosi tylko ~0,00000009%. Ale w przypadku większych zakresów lub wartości 8-bitowych staje się to znaczące.

Ukryte filtry

Niektóre systemy losowania dyskretnie wykluczają pewne wyniki (np. odfiltrowując „ostatnich zwycięzców” lub wyniki ponownego losowania, które nie podobają się operatorowi). Narusza to uczciwość, nawet jeśli podstawowy RNG jest doskonały. Udokumentuj i ujawnij wszelkie zasady filtrowania przed losowaniem.

Lista kontrolna audytu dla operatorów

  1. Źródło entropii — Czy RNG pochodzi ze źródła kryptograficznego? (Nie Math.random, nie znaczniki czasu)
  2. Test jednolitości — Przeprowadź ponad 10 000 próbek i zastosuj test chi-kwadrat. wartość p powinna wynosić > 0,05
  3. Odchylenie modulo — Czy w kodzie zastosowano próbkowanie przez odrzucenie lub metodę bezstronnego mapowania?
  4. Niezależność — Czy kolejne losowania są ze sobą skorelowane? Uruchom test autokorelacji na dużych zestawach próbek
  5. Przegląd kodu — Czy kod losowania jest typu open source lub podlega audytowi? Ukryty kod może zawierać backdoory
  6. Ujawnianie filtrów — Czy jakieś wyniki są filtrowane, przerzucane lub wykluczane? Należy to ujawnić
  7. Timing — Czy operator może zobaczyć wyniki przed publikacją? Jeśli tak, może selektywnie odrzucać niekorzystne remisy

Wzór przejrzystości dla loterii publicznych

W przypadku losowań o wysokie stawki (nagrody, przydziały, selekcje) użyj schematu zatwierdzenia-ujawnienia:

  1. Przed losowaniem: Wygeneruj losowe ziarno. Opublikuj swój skrót SHA-256 („zobowiązanie”) — np. w mediach społecznościowych lub dokumencie ze znacznikiem czasu
  2. Przeprowadź losowanie: Użyj nasion do wygenerowania wyników za pomocą algorytmu deterministycznego
  3. Po losowaniu: Opublikuj nasiono. Każdy może to sprawdzić:
    • Nasiono generuje opublikowany skrót
    • Nasiono + algorytm generuje ogłoszone wyniki

Użyj naszego Generatora skrótów, aby utworzyć i zweryfikować skrót zobowiązania.

// Faza zaangażowania
const nasion = crypto.randomBytes(32).toString('hex');
stałe zaangażowanie = sha256(ziarno); // opublikuj to przed losowaniem // Faza losowania
const wynik = deterministicDraw(nasiono, uczestnicy); // Faza ujawnienia
// opublikuj materiał siewny — każdy może zweryfikować sha256(nasiono) === zaangażowanie

Przekazywanie użytkownikom zasad uczciwości

Zaufanie wymaga przejrzystości. Podczas przeprowadzania losowań publicznych:

FAQ

Czy Math.random jest wystarczająco dobry?

Nie. Math.random() używa generatora liczb pseudolosowych (PRNG), który nie jest bezpieczny kryptograficznie. Jego wynik można przewidzieć, jeśli znany jest stan wewnętrzny. W przypadku uczciwych losowań użyj crypto.getRandomValues() w przeglądarce lub crypto.randomInt() w Node.js.

Jak mogę udowodnić, że losowanie nie zostało zmanipulowane?

Użyj schematu zatwierdzenia i ujawnienia: przed losowaniem opublikuj skrót losowego ziarna (zobowiązanie). Po losowaniu odkryj ziarno. Każdy może sprawdzić, czy ziarno generuje opublikowany skrót i ogłoszone wyniki.

Ile próbek potrzebuję do podstawowej kontroli błędu systematycznego?

Do prostego sprawdzenia jednorodności N wyników potrzeba co najmniej 100×N próbek (np. 1000 próbek w przypadku losowania z 10 opcjami). Zastosuj test chi-kwadrat: jeśli wartość p przekracza 0,05, rozkład jest w miarę równomierny. W przypadku poważnych audytów użyj ponad 10 000 próbek.

Powiązane narzędzia i artykuły