Gerador de string aleatória em PHP: como funciona por dentro
\n\nTodo desenvolvedor já enfrentou a tarefa de gerar uma string aleatória. Seja para tokens, senhas temporárias, IDs de sessão ou apenas dados de teste. No PHP, existem dezenas de maneiras de fazer isso, mas qual é a correta? E, mais importante — por quê?
\n\nNo Stack Overflow, a pergunta "PHP random string generator" acumulou milhares de visualizações e centenas de respostas. Mas a maioria delas são apenas snippets prontos, sem explicação. Hoje, vamos mergulhar nos bastidores do PHP e entender como os geradores de strings aleatórias realmente funcionam, qual a diferença entre rand() e random_int() e por que sua "senha aleatória" pode não ser tão aleatória assim.
O que é "aleatoriedade" no PHP?
\n\nNa programação, a aleatoriedade é dividida em dois tipos: pseudoaleatoriedade e aleatoriedade criptograficamente segura. A diferença entre elas é como a diferença entre um dado de jogo e uma calculadora previsível.
\n\nNúmeros pseudoaleatórios (PRNG) são gerados por um algoritmo baseado em uma semente inicial (seed). Se você conhece a semente, conhece toda a sequência. Para tarefas simples (como randomizar uma cor no design ou gerar dados de teste), isso é suficiente. Mas para tokens de autenticação e senhas, é um desastre.
\n\nO PHP oferece várias funções, e cada uma representa um nível diferente de "aleatoriedade":
\n\n- \n
rand()— o PRNG clássico, rápido, mas previsível \n mt_rand()— algoritmo melhorado Mersenne Twister, mais rápido e com período maior \n random_int()erandom_bytes()— geradores criptograficamente seguros (PHP 7+) \n openssl_random_pseudo_bytes()— outra opção criptograficamente segura \n
Como funciona o snippet mais popular?
\n\nAqui está o código clássico que circula pela internet:
\n\n<?php\nfunction generateRandomString($length = 10) {\n $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n $charactersLength = strlen($characters);\n $randomString = '';\n for ($i = 0; $i < $length; $i++) {\n $randomString .= $characters[rand(0, $charactersLength - 1)];\n }\n return $randomString;\n}\n?>\n\nÀ primeira vista, parece lógico. Pegamos uma string com caracteres, escolhemos um índice aleatório e repetimos. Mas vamos analisar o que realmente está acontecendo aqui.
\n\nProblema nº1: rand() e sua semente
\n\nA função rand() no PHP usa, por padrão, o algoritmo Linear Congruential Generator (LCG). Este é um dos métodos mais antigos e mais previsíveis. Se você não chamar srand() com uma semente aleatória, o PHP inicializa automaticamente o gerador com a hora atual (em microssegundos).
Sabendo o horário exato da execução do script (por exemplo, a partir dos logs do servidor), um invasor pode reproduzir toda a sequência de rand(). Para um token de recuperação de senha, isso é um caminho direto para a invasão.
Problema nº2: Viés de probabilidade (Bias)
\n\nMesmo sem pensar em segurança, há um problema matemático. Imagine que rand(0, 61) (62 caracteres na string). O PHP internamente usa um intervalo de 0 a getrandmax() (geralmente 2147483647). 2147483647 não é divisível exatamente por 62. O resto da divisão é 31. Isso significa que os primeiros 31 números do intervalo têm uma probabilidade ligeiramente maior de sair do que os outros.
Na prática, a diferença é mínima, mas se você precisa de uma string aleatória com distribuição uniforme, rand() não é a melhor escolha. random_int() resolve esse problema usando um algoritmo que garante distribuição uniforme.
Gerador criptograficamente seguro: o que tem por dentro?
\n\nNo PHP 7, surgiram as funções random_int() e random_bytes(). Elas usam a fonte de entropia do sistema:
- \