← Voltar ao Blog

O seu gerador de números aleatórios é justo? Lista de verificação prática de auditoria

Ferramentas e justiça30 de março de 2026·7 min de leitura
Random number generator fairness audit

Quando você realiza um sorteio, escolhe equipes aleatoriamente ou atribui tarefas por sorteio, a justiça não é opcional - é o ponto principal. Mas “aleatório” não significa automaticamente “justo”. Vieses ocultos em geradores de números aleatórios (RNGs) podem distorcer os resultados de maneiras invisíveis, a menos que você saiba onde procurar.

Este artigo fornece uma lista de verificação prática para auditar qualquer RNG quanto à imparcialidade, esteja você usando nosso Gerador de números aleatórios ou construindo o seu próprio.

O que significa justiça para sorteios voltados para o usuário

Um RNG justo produz resultados onde:

A falta de qualquer um desses quebra a confiança, mesmo que os resultados "pareçam" aleatórios.

Fontes comuns de preconceito

Sementes ruins

Um PRNG (gerador de números pseudo-aleatórios) é tão imprevisível quanto sua semente. Sementes ruins comuns:

Sempre propagar de uma fonte criptográfica: crypto.getRandomValues() em navegadores, /dev/urandom no Linux, ou crypto.randomBytes() em Node.js.

Módulo Bias

Um bug sutil e comum: usar o operador módulo para reduzir um número aleatório a um intervalo.

// BIASED — se o intervalo RNG não for múltiplo de 6,
// alguns resultados são ligeiramente mais prováveis
const roll=randomUint32()% 6; // CORRETO — amostragem de rejeição
function fairDiceRoll() { const max = Math.floor(0xFFFFFFFF/6) * 6; deixe valor; faça { value = crypto.getRandomValues(new Uint32Array(1))[0]; } while (valor >= max); valor de retorno% 6;
}

Para um dado de 6 lados, a polarização do módulo com um número inteiro de 32 bits é de apenas ~0,00000009%. Mas para intervalos maiores ou valores de 8 bits, torna-se significativo.

Filtros ocultos

Alguns sistemas de sorteio excluem silenciosamente certos resultados (por exemplo, filtrando "vencedores recentes" ou relançando resultados que o operador não gosta). Isto viola a justiça, mesmo que o RNG subjacente seja perfeito. Documente e divulgue quaisquer regras de filtragem antes do sorteio.

Lista de verificação de auditoria para operadores

  1. Fonte de entropia — O RNG é propagado a partir de uma fonte criptográfica? (Não Math.random, nem carimbos de data e hora)
  2. Teste de uniformidade — Execute mais de 10.000 amostras e aplique um teste qui-quadrado. O valor p deve ser> 0,05
  3. Modulo bias — O código usa amostragem de rejeição ou um método de mapeamento imparcial?
  4. Independence — Os sorteios sequenciais estão correlacionados? Execute um teste de autocorrelação em grandes conjuntos de amostras
  5. Revisão do código — O código do sorteio é de código aberto ou auditável? O código oculto pode conter backdoors
  6. Divulgação de filtragem — Algum resultado foi filtrado, relançado ou excluído? Isso deve ser divulgado
  7. Timing — O operador pode ver os resultados antes de publicar? Se sim, eles podem descartar seletivamente empates desfavoráveis

Padrão de transparência para sorteios públicos

Para sorteios de apostas altas (prêmios, atribuições, seleções), use um esquema de compromisso-revelação:

  1. Antes do sorteio: Gere uma semente aleatória. Publique seu hash SHA-256 (o "compromisso") — por exemplo, nas redes sociais ou em um documento com carimbo de data/hora
  2. Execute o sorteio: Use a semente para gerar resultados com um algoritmo determinístico
  3. Após o sorteio: Publicar o seed. Qualquer pessoa pode verificar isso:
    • A semente produz o hash publicado
    • O algoritmo seed + produz os resultados anunciados

Use nosso Hash Generator para criar e verificar o hash de compromisso.

// Fase de compromisso
const semente = crypto.randomBytes(32).toString('hex');
compromisso const = sha256(semente); // publica isso antes do sorteio // Fase de desenho
resultado const = deterministicDraw(semente, participantes); // Fase de revelação
// publica seed — qualquer um pode verificar sha256(seed) === comprometimento

Como comunicar justiça aos usuários

Confiança requer transparência. Ao realizar sorteios públicos:

FAQ

Math.random é bom o suficiente?

Não. Math.random() usa um gerador de números pseudo-aleatórios (PRNG) que não é criptograficamente seguro. Sua saída pode ser prevista se o estado interno for conhecido. Para sorteios justos, use crypto.getRandomValues() no navegador ou crypto.randomInt() em Node.js.

Como posso provar que um empate não foi manipulado?

Use um esquema commit-reveal: antes do sorteio, publique um hash da semente aleatória (compromisso). Após o sorteio, revele a semente. Qualquer pessoa pode verificar se a semente produz o hash publicado e os resultados anunciados.

Quantas amostras são necessárias para verificações básicas de polarização?

Para uma verificação simples de uniformidade em N resultados, você precisa de pelo menos 100×N amostras (por exemplo, 1.000 amostras para um sorteio de 10 opções). Aplique um teste qui-quadrado: se o valor p estiver acima de 0,05, a distribuição é razoavelmente uniforme. Para auditorias sérias, use mais de 10.000 amostras.

Ferramentas e artigos relacionados