Como realmente funciona o gerador de strings aleatórias em PHP? Olhando por baixo dos panos
Você já se perguntou o que acontece quando você clica em "Gerar senha" em um site? Ou quando o sistema cria um identificador único para sua sessão? Em nove entre dez casos, por trás disso está um gerador de strings aleatórias em PHP. Parece simples: pegue um array de caracteres, embaralhe, exiba o resultado. Mas o diabo, como sempre, está nos detalhes.
No Stack Overflow, a pergunta "PHP random string generator" acumulou milhares de visualizações. E não é por acaso. Iniciantes escrevem soluções improvisadas com rand(), experientes usam random_int(), e os gurus debatem sobre entropia. Vamos entender como tudo funciona de verdade e escrever nosso gerador ideal.
Por que rand() é um problema? (spoiler: previsibilidade)
A forma mais popular e "infantil" é usar rand() em um loop:
<?phpfunction generateRandomString($length = 10) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString;}echo generateRandomString(); // Saída: "aB3kL9xQ2m"?>O código funciona. Mas apenas se você não se importa com segurança. A função rand() usa um gerador linear congruencial (LCG). É um algoritmo determinístico: conhecendo o estado atual, é possível prever todos os números seguintes. Além disso, rand() é inicializado com 1 por padrão, se você não chamar srand(). E se chamar, a semente geralmente vem de time(), o que oferece apenas 2-3 milhões de possibilidades. A força bruta leva segundos.
Conclusão: rand() serve para jogos e escolhas aleatórias de avatar, mas não é absolutamente adequado para gerar tokens, senhas ou chaves de API.
Conheça mt_rand() — mais rápido, mas não mais seguro
No PHP 4, surgiu o mt_rand(), baseado no Mersenne Twister. Ele é mais rápido e tem um período melhor (2^19937 contra 2^31 do rand). Muitos ainda o usam como uma versão "avançada":
<?phpfunction generateTokenMtRand($length = 32) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $token = ''; for ($i = 0; $i < $length; $i++) { $token .= $chars[mt_rand(0, strlen($chars) - 1)]; } return $token;}?>Mas aqui também há um problema. O Mersenne Twister é criptograficamente inseguro. A partir de uma sequência de 624 números gerados, é possível recuperar o estado interno do gerador e prever todos os valores futuros. Para atacar um token de redefinição de senha, isso é mais que suficiente.
Moral da história: mt_rand() é uma ótima escolha para simulações e testes, mas não para segurança.
A santíssima trindade: random_int(), CSPRNG e entropia
A partir do PHP 7.0, temos random_int() e random_bytes(). Estes são geradores de números pseudoaleatórios criptograficamente seguros (CSPRNG). O que isso significa na prática?
- Entropia: O PHP coleta "ruído" do sistema: tempo entre pressionamentos de teclas, movimentos do mouse, pacotes de rede, interrupções de disco. No Linux, usa-se
/dev/urandom; no Windows,CryptGenRandom. - Imprevisibilidade: Mesmo conhecendo o algoritmo, não é possível recuperar a semente ou prever o próximo número.
- Distribuição uniforme: Cada byte tem exatamente 1/256 de probabilidade de ocorrer.
Veja como é um gerador de strings aleatórias correto em PHP