Gerar números aleatórios no Linux com random e urandom

Como gerar números aleatórios no Linux com random e urandom

Podemos gerar dados e números aleatórios no Linux para uma série de tarefas importantes, como tarefas relacionadas à segurança, reinicializar dispositivos de storage, apagar e sobrescrever dados existentes e até mesmo gerar dados sem sentido para realização de testes.

Podemos gerar números aleatórios usando a variável de ambiente $RANDOM, que é derivada do gerador de números aleatórios do kernel do Linux. Essa variável retorna na verdade um inteiro pseudo aleatório de 16 bits, no intervalo entre 0 e 32767.

Podemos também funções da biblioteca OpenSSL, a qual utiliza o algoritmo FIPS140 para gerar números aleatórios, que são então usados para criptografia.

Falaremos neste tutorial sobre o método que usa a variável de ambiente $RANDOM.

Geração de Números Aleatórios pelo Kernel

Para entendermos a geração de números aleatórios pelo kernel é importante entendermos o conceito de Entropia.

Para que tenhamos segurança computacional suficiente, os números aleatórios devem ser extremamente difíceis de adivinhar, ou seja, devem ser altamente imprevisíveis. Essa previsibilidade dos números pode ser quantificada com uma medida chamada Entropia.

A entropia é, de forma bastante simplificada, uma medida do número de maneiras em que um sistema pode ser organizado, sendo na verdade uma medida da desordem ou aleatoriedade do sistema.

No Linux, a aleatoriedade é derivada do Pool de Entropia do Kernel. Trata-se de um número grande (4096 bits) mantido na memória de forma privativa. 4096 bits significa que existem 24096 possibilidades distintas para esse valor, ou seja, ele pode conter até 4096 bits de entropia. Essa memória é “preenchida” com esses bits a partir de fontes que contenham entropia suficiente, portanto, a aleatoriedade necessária.

Esse pool de entropia é então usado para gerar números aleatórios, e ele é realimentado com entropia pelo kernel. Quando um número aleatório é gerado, o pool de entropia diminui, pois uma parte de seu conteúdo foi usada, e ele deve ser preenchido novamente.

Podemos ver o nível de entropia aproximado atual do sistema usando o seguinte comando:

# cat /proc/sys/kernel/random/entropy_avail

Emitindo o comando sequencialmente, podemos ver o nível de entropia diminuindo no pool.

A entropia no pool é preenchida novamente quando determinados eventos ocorrem no sistema. Basicamente, o kernel usará o relógio interno do sistema, acessos à rede a aos discos e periféricos como fontes de entropia para seu pool.

Alguns servidores possuem geradores de números aleatórios (RNG – Random Number Generator) em hardware que recebem como entrada vários tipos de sinais de ruído diferentes, como ruído térmico por exemplo. Esse ruído é então convertido em sinais elétricos que podem então ser novamente convertidos, desta vez em números digitais com o uso de um conversor A-D. Já a maioria dos computadores não possuem hardware desse tipo, usando com fontes de ruído eventos que ocorrem com o próprio sistema para criar os números aleatórios.

O Kernel do Linux utiliza os dispositivos /dev/random e /dev/urandom para gerar números aleatórios, os quais se alimentam de dados do pool de entropia do sistema. Esses dispositivos fornecem uma interface para o gerador de números aleatórios do Kernel.

O dispositivo /dev/random deve ser utilizado quando necessitamos de um grau de aleatoriedade mais alto, como por exemplo na geração de chaves do tipo one-time pad. Em contrapartida, é relativamente lento para gerar os números aleatórios. Se o pool de entropia estiver vazio, esse dispositivo será bloqueado e não gerará nenhum número até que ruído ambiental seja coletado; por ruído ambiental entende-se frequência de digitação de teclas, movimentos do mouse, tráfego de rede, etc.

Já o dispositivo /dev/urandom é mais rápido e pode ser suficiente para a maioria das funções criptográficas comuns. Esse dispositivo reusa o pool interno do sistema para gerar bits pseudo aleatórios. Portanto, possui menos entropia que o uso do /dev/random, e não deve ser usado para a geração de chaves criptográficas de longa duração como chaves GPG, SSL e SSH..

Caso o seu sistema não possua esses arquivos de dispositivos já criados, você pode criá-los emitindo a sequência de comandos abaixo:

# mknod -m 644 /dev/random c 1 8
# mknod -m 644 /dev/urandom c 1 9
# chown root:root /dev/random /dev/urandom

Tamanho do pool de entropia:

Podemos verificar o tamanho do pool de entropia do kernel acessando o arquivo:

# cat /proc/sys/kernel/random/poolsize

ou em sistemas Red Hat:

# sysctl kernel.random.poolsize

O tamanho padrão atualmente é de 4096 bits.

Vamos gerar números aleatórios agora:

1. Usando a variável $RANDOM diretamente:

$ echo $RANDOM

Números aleatórios com $RANDOM no Linux

Veja que foi gerado o número 19548. Se for executado novamente, esse comando irá gerar outro número qualquer.

2. Podemos alimentar o gerador de números aleatórios fornecendo um valor inicial à variável $RANDOM. De preferência um número que seja difícil de prever. Podemos, por exemplo, usar o número de segundos decorridos desde 01/01/1970, por meio do comando date +%s, para alimentar (seed) a variável $RANDOM:

$ RANDOM=$(date +%s)
$ echo $RANDOM

Criar números aleatórios no Linux

Perceba que o número gerado não possui relação aparente com o valor em segundos que o comando date retorna.

3. Lendo dados do dispositivo /dev/random e exibindo o número no terminal:

$ RANDOM=$(dd if=/dev/random bs=5 count=1)
$ echo $RANDOM

Arquivos aleatórios no Linux com random

4. Vamos agora gerar senhas aleatórias com caracteres alfabéticos a partir do dispositivo /dev/urandom. Usaremos alguns comandos conectados via pipes para as conversões. E usaremos o comando time para obter estatísticas de tempo de execução do comando:

$ time cat /dev/urandom | tr -dc 'a-zA-Z' | fold -w 8 | head -n 5

Números aleatórios com urandom no Linux

Neste exemplo criamos 5 senhas com 8 caracteres cada uma. Veja que o processo foi extremamente rápido.

Usamos alguns comandos não muito comuns no exemplo. Vejamos sucintamente o que eles fazem:

tr -dc ‘a-zA-Z’ Trazer apenas caracteres alfabéticos, maiúsculos e minúsculos.

fold -w 8 Comprimento do ponto de corte da string que será gerada

head -n 5 Trazer apenas as 5 primeiras linhas. Esse comando é bem comum.

É isso aí! Vimos neste artigo alguns conceitos sobre geração de números e valores aleatórios no Linux. Nos próximos artigos falaremos muito mais sobre tópicos de segurança do sistema.

Sobre Fábio dos Reis (1317 Artigos)
Fábio dos Reis trabalha com tecnologias variadas há mais de 25 anos, tendo atuado nos campos de Eletrônica, Telecomunicações, Programação de Computadores e Redes de Dados. É um entusiasta de Unix, Linux e Open Source em geral, adora Eletrônica e Música, e estuda idiomas, além de ministrar cursos e palestras sobre diversas tecnologias em São Paulo e outras cidades do Brasil.
Contato: Website

Escreva um comentário

Seu e-mail não será divulgado


*