A
LEATÓRIOS
À parte o questionamento filosófico, ou matemático, sobre a existência ou não de números aleatórios, sabe-se que números, com características de aleatoriedade, são de interesse não só da comunidade acadêmica, mas também da sociedade em geral. Isso se deve às inúmeras utilizações desses números em segurança de sistemas, simulações computacionais, amostragem de dados, geração de senhas, análises numéricas, tomada de decisões, recreação (jogos), criptografia, estética (música) etc. É longa a lista de aplicações de tais números e grandes são os desafios ligados às suas descobertas.
Essa busca não se limita aos tempos atuais. No início do século XX esses números eram obtidos com a retirada, ao acaso, de bolas em uma urna. Também eram obtidos com o lançamento de dados ou com a distribuição de cartas. O avanço da tecnologia fez com que dispositivos fossem criados para tal propósito. O surgimento dos computadores e o desenvolvimento de programas impulsionou a produção de números aleatórios. As sequências aleatórias geradas em computadores ou outros equipamentos determinísticos recebem o nome de sequências pseudoaleatórias. A seguir, apresentamos os dois grandes grupos de geradores de números aleatórios.
3.1 Geradores de números verdadeiramente aleatórios
(TRNGs)
Nos geradores de números verdadeiramente aleatórios (True Random Number Generator ou TRNGs) as sequências de bits aleatórios são obtidas das fontes de ruídos, que são a fonte de entropia desses geradores. Esse é um processo não determinístico de fornecimento de entropia, o qual é responsável pela incerteza associada à saída das sequências de bits. As fontes de ruídos podem ser divididas em duas categorias: (a) Fontes de ruídos físicos, que utilizam hardware dedicado para
prover aleatoriedade; e (b) Fontes de ruídos não físicos, que utilizam dados do sistema ou intervenção humana para prover a aleatoriedade dos TRNGs [BARKER 2012 ].
Podemos citar como exemplos algumas fontes de ruídos não físicos: 1. o valor instantâneo do relógio do sistema;
2. tempo decorrido entre pressionamentos de teclas ou entre cliques no mouse;
3. conteúdo de buffers de entrada e saída; 4. dados de entrada do usuário;
5. valores do sistema operacional, como carga do sistema e estatísticas da rede.
Exemplos de fontes de ruídos físicos:
1. tempo decorrido entre a emissão de partículas durante o decaimento radioativo;
2. ruído térmico de um diodo ou resistor semicondutor; 3. a instabilidade de frequência de um oscilador;
4. variação na latência de acesso a setores de discos rígidos causada pela turbulência do ar dentro de uma unidade de disco selada;
5. sinais de som de um microfone ou de vídeo de uma câmera.
3.2 Geradores de números pseudoaleatórios (PRNGs)
Os PRNGs produzem seus números de forma determinística, que não podem ser chamados de números verdadeiramente aleatórios. Existem vários algoritmos para PRNGs: Linear Congruential Generators, Linear Feedback Shift Registers, Generalized Fibonacci Generators, geradores criptográficos, Quadratic Congruential Generators e Cellular Automaton Generators. A Figura 3.1 ilustra uma ideia de um PRNG, o qual também é conhecido como um gerador de números aleatórios determinístico e, portanto, é responsável por gerar sequências de bits a partir de um estado inicial, conhecido como semente.
A determinação se a sequência de bits é aleatória ou não se dá por intermédio de testes de aleatoriedade, existindo vários conhecidos nos meios acadêmicos.
Figura 3.1 Geração de bits pseudoaleatórios a partir de um estado inicial.
3.2.1 Exemplo de PRNG: o gerador congruente linear
É um algoritmo que produz uma sequência de números pseudoaleatórios chamado gerador congruente linear (do inglês Linear congruential generator) também conhecido como LCG, o qual utiliza uma função linear em trecho.
Esse método representa um dos geradores de números pseudoaleatórios mais antigos e mais conhecidos. Sua implementação é simples, de fácil compreensão e sua execução e bastante rápida, sendo definida por uma relação de recorrência:
Gn+1 = (rGn + t) mod m
onde:
G: é a sequência de valores pseudoaletórios a ser gerada; m: é o módulo, sendo m < 0;
b: é o multiplicador, sendo 0 < b < m; f: é o incremento, sendo 0 𝑓 𝑚;
G0: é a semente ou valor inicial, sendo 0 𝐺0 𝑚;
As sementes são constantes inteiras que definem o gerador. Se f = 0, o gerador é comumente chamado de gerador congruente multiplicativo, referenciado pela sigla MCG ou Lehmer RNG. Caso f 0 o gerador é chamado de congruente misto. Enquanto esse gerador é muito usado para fins de simulação e algoritmos probabilísticos, e passa nos testes estatísticos, eles são previsíveis e, totalmente
inseguros para propósitos criptográficos, assim, dada uma seqüência de saída parcial, o restante da sequência pode ser reconstruída mesmo se os parâmetros r, t, e m forem desconhecidos, como apresentado em [Knuth 1985].
3.2.2 Gerador de números aleatórios do Linux (LRNG)
A geração de números aleatórios no Linux envolve a coleta e armazenamento de bits aleatórios em três repositórios, como pode ser observado na Figura 3.2 extraída de [GUTTERMAN 2006]. O primeiro repositório de 512 bytes coleta bits aleatórios de diversos eventos do sistema operacional, tais como intervalos entre acionamentos de teclas ou de mouse, intervalos entre interrupções ou intervalos entre acessos ao disco. Recentemente a Intel e outros fabricantes de CPUs começaram a integrar TRNGs dentro de seus chips, como está descrito no Apêndice 1. Esse primeiro repositório alimenta outros dois com seus bits verdadeiramente aleatórios (sementes).
Deve ser notado que a taxa de geração desses bits para o primeiro repositório (mesmo os bits produzidos por hardware TRNG) pode ser relativamente baixa, se comparada à demanda de bits aleatórios de muitas aplicações. Por isso é comum se recorrer a PRNGs para complementar o trabalho dos TRNGs.
O segundo repositório tem 128 bytes e oferece uma interface para aplicações coletarem os bits disponíveis (lendo de /dev/random). Se a aplicação demandar mais bits que os disponíveis, ela será bloqueada, até que novos bits aleatórios sejam armazenados.
O terceiro repositório, também de 128 bytes, é chamado de Urandom e também oferece uma interface para as aplicações (/dev/urandom). Entretanto, essa interface não é bloqueante e consegue entregar bits aleatórios a taxas muito maiores do que as taxas em que eles são gerados. Sendo assim, ela é a interface a ser usada por aplicações que demandam grande número de bits aleatórios em pouco tempo.
A geração de bits aleatórios que alimentam o repositório Urandom é feita por uma função determinística que pode ser definida em tempo de compilação do kernel. Normalmente é utilizada a função de hash criptográfico SHA-1 (Secure Hash Algorithm), a qual produz vários bits pseudoaleatórios a partir de sementes que são coletadas dos bytes do próprio repositório Urandom.
Além disso, a própria função retorna alguns dos bits produzidos por ela para o mesmo repositório, ajudando a mantê-lo sempre com sua entropia em níveis aceitáveis. Sendo assim, é possível entregar com Urandom uma grande quantidade de bits (pseudo)aleatórios às aplicações sem que estas sejam bloqueadas à espera pela produção de novos bits aleatórios nas fontes de entropia.
Figura 3.2 Estrutura básica do gerador de números aleatórios do Linux (fonte: Gutterman 2006)
3.3 Principais propriedades para geradores de números
pseudoaleatórios PRNGs
Um gerador de números pseudoaleatórios (PRNG) é um algoritmo determinístico que, de uma sequência verdadeiramente aleatória de comprimento s (estado inicial), produz uma sequência binária de comprimento l (geralmente maior que s), que deve parecer aleatória. A entrada de um PRNG é chamada de semente, enquanto a saída é chamada de sequência de bits pseudoaleatórios.
Para declarar que os ACs são geradores de números aleatórios adequados, os bits que eles produzem devem ser submetidos a testes estatísticos que são projetados para detectar características específicas esperadas de sequências aleatórias. No entanto, passar nos testes estatísticos é uma condição necessária, mas
não suficiente, para que um gerador seja considerado seguro, isto é, adequado para aplicações criptográficas.
Portanto, nesta seção examinaremos algumas das principais propriedades de um PRNGs, tais como: tamanho do estado interno, período, previsibilidade, segurança criptográfica, desempenho temporal e espacial e tamanho do código.