Melhor geração aleatória de PHP
Pergunta
Eu sei que apenas usando rand()
é previsível, se você souber o que está fazendo e tiver acesso ao servidor.
Eu tenho um projeto que é altamente depende da escolha de um número aleatório que seja tão imprevisível quanto possível.Então, estou procurando sugestões, sejam outras funções internas ou funções do usuário, que possam gerar um melhorar número aleatório.
Usei isso para fazer um pequeno teste:
$i = 0;
while($i < 10000){
$rand = rand(0, 100);
if(!isset($array[$rand])){
$array[$rand] = 1;
} else {
$array[$rand]++;
}
sort($array);
$i++;
}
Descobri que os resultados estão distribuídos uniformemente e há um padrão estranho no número de vezes que cada número é gerado.
Solução
Adicionar, multiplicar ou truncar uma fonte aleatória ruim resultará em um resultado aleatório ruim.Ver Introdução à aleatoriedade e aos números aleatórios para uma explicação.
Você está certo sobre a função PHP Rand().Veja a segunda figura em Análise Estatística para uma ilustração impressionante.(A primeira figura é impressionante, mas foi desenhada por Scott Adams, não plotada com Rand()).
Uma solução é usar um gerador aleatório verdadeiro, como aleatório.org.Outra, se você estiver no Linux/BSD/etc.é usar /dev/aleatório.Se a aleatoriedade for de missão crítica, você terá que usar um gerador aleatório de hardware.
Outras dicas
aleatório.org tem uma API que você pode acessar via HTTP.
Random.org é um verdadeiro serviço de números aleatórios que gera aleatoriedade através do ruído atmosférico.
Eu ficaria cauteloso com a impressão de aleatoriedade:houve muitos experimentos em que as pessoas escolheriam a distribuição menos aleatória.Parece que a mente não é muito boa em produzir ou estimar a aleatoriedade.
Existem bons artigos sobre aleatoriedade em Fourmilab, incluindo outro gerador aleatório verdadeiro.Talvez você possa obter dados aleatórios de ambos os sites, então, se um estiver inativo, você ainda terá o outro.
Fourmilab também fornece um programa de teste para verificar a aleatoriedade.Você poderia usá-lo para verificar seus vários programas myRand().
Quanto ao seu último programa, se você gera 10.000 valores, por que não escolhe o valor final entre os 10 mil?Você se restringe a um subconjunto.Além disso, não funcionará se $min e $max forem maiores que 10.000.
De qualquer forma, a aleatoriedade necessária depende da sua aplicação.rand() será adequado para um jogo online, mas não adequado para criptografia (qualquer coisa que não seja completamente testada com programas estatísticos não será adequada para criptografia de qualquer maneira).Você é o juíz!
Variação em @KG, usando os milissegundos desde EPOCH como semente para rand?
Outra maneira de obter números aleatórios, semelhante em conceito ao UUID
PHP versão 5.3 e superior
openssl_random_pseudo_bytes(...)
Ou você pode tentar o seguinte biblioteca usando RFC4122
Um novo PHP7 existe uma função que faz exatamente o que você precisava:isso gera inteiros pseudo-aleatórios criptograficamente seguros.
int random_int ( int $min , int $max )
Gera números inteiros aleatórios criptográficos que são adequados para uso onde resultados imparciais são críticos (ou seja,embaralhar um baralho de pôquer).
Para uma explicação mais detalhada sobre PRNG e CSPRNG (e suas diferenças), bem como por que sua abordagem original é na verdade uma má ideia, leia meu outra resposta altamente semelhante.