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 número seguinte pode, de facto, ser previsto depende do tipo de gerador. Alguns geradores baseiam-se num processo físico, outros calculam os números com um algoritmo, e alguns algoritmos são construídos de forma que nem quem viu os 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 gerador de números verdadeiramente aleatórios (TRNG), obtém os seus números de um processo físico. Os mais antigos funcionam diante dos nossos olhos: uma moeda atirada ao ar, um dado lançado, 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 na forma como cada giro começa se transformam em resultados completamente diferentes.
Os geradores de hardware modernos medem, em vez disso, fenómenos microscópicos: o ruído de disparo (shot noise) e o ruído térmico em circuitos eletrónicos, o ruído atmosférico, efeitos quânticos. São boas fontes de entropia — imprevisibilidade que pode ser medida —, mas uma fonte física não é perfeita por natureza: pode ter enviesamentos, pode derivar com o tempo e pode falhar, pelo que a sua qualidade tem de ser avaliada e monitorizada, e os seus resultados processados quando necessário, como descrevem normas como a NIST SP 800-90B. As fontes de hardware são usadas onde a garantia mais importa — sobretudo na criptografia, onde fornecem o material inicial imprevisível para as chaves 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 que é totalmente determinada por um valor inicial chamado semente (seed). Dê a mesma semente ao mesmo algoritmo e obterá sempre a mesma sequência. Isso é uma fraqueza sempre que o resultado tem de ser imprevisível e a semente ou o estado interno podem ser adivinhados ou reconstruídos, e uma vantagem sempre que o resultado tem de ser reprodutível — uma simulação ou um teste podem ser repetidos exatamente. Os PRNG são também rápidos, baratos e fáceis de implementar, e é por isso que a maior parte do software depende deles. Entre as famílias conhecidas contam-se 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 a opção predefinida em muitas linguagens de programação. O nome vem do seu período — o comprimento da sequência antes de se repetir —, que na variante padrão, MT19937, é o primo de Mersenne 219937 − 1. Passa na maioria dos testes estatísticos de aleatoriedade e adequa-se bem a simulações. No entanto, não foi concebido para guardar segredos: a partir de 624 resultados consecutivos de 32 bits, qualquer pessoa consegue reconstruir o seu estado interno e prever todos os valores seguintes, pelo que não deve ser usado para chaves, palavras-passe ou qualquer outra coisa que tenha de permanecer imprevisível.
Geradores criptograficamente seguros e entropia
Muitas aplicações precisam das duas coisas ao mesmo tempo: a rapidez de um algoritmo e a imprevisibilidade de uma fonte física. A resposta é um gerador de números pseudoaleatórios criptograficamente seguro (CSPRNG). Continua a ser um PRNG, mas construído de forma que ver parte dos seus resultados não dá nenhuma forma prática de prever o resto, e recebe uma semente, renovada regularmente, a partir de uma fonte de entropia real. Uma semente de origem física não torna seguro um PRNG comum; o próprio algoritmo tem de ser concebido 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 verdadeira, e o CSPRNG obtém dela, muito mais depressa, uma longa sequência de valores. Esta combinação é o que um sistema operativo oferece aos programas que nele correm, e é o que hoje, na prática, se entende normalmente por «gerador de números aleatórios». É ele que produz chaves de cifra, tokens de sessão e palavras-passe.
Números aleatórios no navegador
O JavaScript dá a uma página web duas formas nativas de obter valores aleatórios, e pertencem a classes diferentes. O Math.random() é um PRNG comum: a norma da linguagem deixa o algoritmo ao critério de cada navegador e não promete nada quanto a segurança — serve para uma animação, mas não para um sorteio que alguém possa contestar. A outra é a Web Crypto API. O seu método crypto.getRandomValues() devolve valores aleatórios criptograficamente fortes, produzidos por um CSPRNG cuja semente vem da entropia do sistema operativo.
O nosso gerador de números aleatórios online usa a Web Crypto API em cada sorteio, e os números são produzidos no seu navegador e não num servidor. A mesma fonte alimenta os outros geradores deste site, quer queira lançar dados, jogar cara ou coroa ou gerar uma palavra-passe.
De bits aleatórios a um número no seu intervalo
Um gerador criptograficamente seguro é apenas metade de um sorteio justo. Fornece bits brutos, e o programa ainda tem de os transformar num número do seu intervalo — e é aqui que pode surgir um enviesamento. Suponha que a fonte dá os valores de 0 a 9 com probabilidades iguais e que precisa de um número de 0 a 5. Tirar o resto da divisão por 6 parece natural, mas então 0, 1, 2 e 3 podem sair de duas formas cada um e 4 e 5 só de uma, pelo que cada número de 0 a 3 tem 20% de probabilidade e 4 e 5 apenas 10% cada um. Uma forma de eliminar o enviesamento é descartar os valores excedentes e sortear de novo; os guias de números aleatórios explicam isto em pormenor.
Há mais duas coisas que surpreendem as pessoas. As repetições são normais: quando se sorteia de forma independente um número inteiro de 1 a 10 e todos os números são igualmente prováveis, o número que acabou de sair tem a mesma probabilidade de 1 em 10 de voltar a sair que qualquer outro. Um sorteio sem repetições é um tipo diferente de sorteio, e não um sorteio mais aleatório. E um gerador justo, por si só, não torna justo todo o processo: a lista de participantes e o número de tentativas contam tanto quanto ele, como explica o nosso guia sobre como sortear um vencedor de concurso.