O que é um gerador de números aleatórios?
Um gerador de números aleatórios (RNG) é um sistema que produz números aleatórios ou pseudoaleatórios. Se o próximo número pode de fato ser previsto depende do tipo de gerador. Alguns geradores se baseiam em um processo físico, outros calculam seus números com um algoritmo, e alguns algoritmos são construídos de modo que nem mesmo quem viu seus resultados consegue prever o que vem a seguir. Parecer aleatório e ser imprevisível são propriedades diferentes, e a maior parte deste artigo trata dessa diferença.
Geradores de números aleatórios por hardware
Um gerador de números aleatórios por hardware (HRNG), também chamado de gerador de números verdadeiramente aleatórios (TRNG), obtém seus números de um processo físico. Os mais antigos funcionam diante dos nossos olhos: uma moeda lançada, um dado rolado, uma roleta. A mecânica descreve cada um deles por completo, mas uma roleta bem construída continua imprevisível na prática, porque diferenças mínimas no início de cada giro se transformam em resultados totalmente diferentes.
Os geradores de hardware modernos medem fenômenos microscópicos: ruído de disparo e ruído térmico em circuitos eletrônicos, ruído atmosférico e efeitos quânticos. Essas são boas fontes de entropia — imprevisibilidade que pode ser medida —, mas uma fonte física não é perfeita por natureza: ela pode apresentar desvios, sofrer variações ao longo do tempo ou falhar, de modo que sua qualidade precisa ser avaliada e monitorada, e seus resultados processados adicionalmente quando necessário, conforme descrito por normas como a NIST SP 800-90B. As fontes de hardware são usadas onde as garantias são mais críticas — sobretudo na criptografia, na qual fornecem o ponto de partida imprevisível para as chaves por trás de protocolos como o Transport Layer Security (TLS).
Geradores de números pseudoaleatórios
A alternativa a um dispositivo físico é um algoritmo. Um gerador de números pseudoaleatórios (PRNG) produz uma sequência que parece aleatória, mas é inteiramente determinada por um valor inicial chamado semente (seed). Dê a mesma semente ao mesmo algoritmo e você obterá a mesma sequência todas as vezes. Isso é uma fraqueza sempre que o resultado precisa ser imprevisível e a semente ou o estado interno podem ser adivinhados ou reconstruídos, e uma vantagem sempre que o resultado precisa ser reproduzível — uma simulação ou um teste pode ser executado novamente de forma idêntica. Os PRNGs também são rápidos, baratos e fáceis de implementar, e por isso a maior parte dos softwares depende deles. Entre as famílias conhecidas estão o gerador congruencial linear (LCG), os geradores xorshift e o Mersenne Twister.
Mersenne Twister
O Mersenne Twister, publicado em 1997 por Makoto Matsumoto e Takuji Nishimura, é um dos geradores de números pseudoaleatórios mais usados e o padrão em muitas linguagens de programação. Seu nome vem do seu período — o comprimento da sequência antes que ela se repita —, que na variante padrão, MT19937, é o primo de Mersenne 219937 − 1. Ele passa na maioria dos testes estatísticos de aleatoriedade e funciona bem em simulações. Contudo, não foi projetado para guardar segredos: a partir de 624 resultados consecutivos de 32 bits, qualquer pessoa consegue reconstruir seu estado interno e prever todos os valores seguintes; portanto, não deve ser usado para chaves, senhas ou qualquer coisa que precise permanecer imprevisível.
Geradores criptograficamente seguros e entropia
Muitas aplicações precisam de ambas as coisas ao mesmo tempo: a velocidade de um algoritmo e a imprevisibilidade de uma fonte física. A resposta é um gerador de números pseudoaleatórios criptograficamente seguro (CSPRNG). Ele ainda é um PRNG, mas construído de modo que observar parte dos seus resultados não oferece uma forma prática de prever o restante; além disso, ele recebe uma semente, e é periodicamente alimentado com novas sementes, a partir de uma fonte de entropia real. Uma semente originada de fonte física não torna seguro um PRNG comum; o próprio algoritmo precisa ter sido projetado para isso. Uma fonte física, como o ruído térmico ou os intervalos entre eventos de hardware, fornece uma pequena quantidade de aleatoriedade autêntica, e o CSPRNG extrai dela, com muito mais rapidez, uma longa sequência de valores. Essa combinação é o que um sistema operacional oferece aos programas executados nele e é o que hoje normalmente se entende, na prática, por “gerador de números aleatórios”. É ele que cria chaves criptográficas, tokens de sessão e senhas.
Números aleatórios no navegador
O JavaScript oferece a uma página web duas formas nativas de obter valores aleatórios, e elas pertencem a categorias distintas. O Math.random() é um PRNG comum: o padrão da linguagem delega o algoritmo a cada navegador e não oferece nenhuma garantia de segurança — serve para uma animação, mas é inadequado para um sorteio que alguém possa contestar. A outra opção é a Web Crypto API. Seu método crypto.getRandomValues() retorna valores aleatórios criptograficamente fortes, produzidos por um CSPRNG inicializado com a entropia do sistema operacional.
Nosso gerador de números aleatórios online usa a Web Crypto API em todos os sorteios, e os números são produzidos no seu navegador, em vez de em um servidor. A mesma fonte alimenta os outros geradores deste site, quer você queira jogar dados, tirar cara ou coroa ou gerar uma senha.
De bits aleatórios a um número no seu intervalo
Um gerador criptograficamente seguro é apenas metade de um sorteio justo. Ele entrega bits brutos, e o programa ainda precisa transformá-los em um número dentro do seu intervalo — e é aqui que chances desiguais (modulo bias) podem surgir. Suponha que a fonte produza valores de 0 a 9 com chances iguais e você precise de um número de 0 a 5. Pegar o resto da divisão por 6 parece uma ideia natural, mas 0, 1, 2 e 3 podem surgir de duas maneiras diferentes, enquanto 4 e 5 só podem surgir de uma; dessa forma, cada número de 0 a 3 fica com 20% de chance, e 4 e 5 com apenas 10% cada. Uma maneira de eliminar essa desigualdade é descartar os valores excedentes e sortear novamente; os materiais sobre números aleatórios explicam isso em detalhes.
Mais dois fatos costumam surpreender as pessoas. Repetições são perfeitamente normais: quando um número inteiro de 1 a 10 é sorteado de forma independente e cada número tem a mesma probabilidade, o número recém-sorteado tem a mesma chance de 1 em 10 de sair novamente que qualquer outro. Um sorteio sem repetições é um tipo diferente de sorteio, e não um sorteio mais aleatório. Além disso, um gerador justo por si só não torna todo o processo justo: a lista de participantes e o número de tentativas importam na mesma medida, como explica nosso artigo sobre como sortear um ganhador de concurso.