Pular para o conteúdo
Todos os conceitos

Prever um gerador pseudoaleatório

Um gerador comum, como o random do Python, tem estado interno; quem descobre o estado prevê todos os próximos números.

Um computador não sorteia nada de verdade. Um gerador pseudoaleatório guarda um estado interno e, a cada pedido, aplica uma fórmula fixa: devolve um número calculado a partir do estado e atualiza o estado. Os números parecem aleatórios, mas quem conhece o estado sabe exatamente quais virão.

O módulo random do Python usa o Mersenne Twister (MT19937). O estado dele são 624 números de 32 bits. Cada saída de random.getrandbits(32) é um desses números passado por uma etapa chamada tempering, feita de deslocamentos e XORs. Essa etapa se desfaz exatamente. Então:

  1. junte 624 saídas seguidas de 32 bits;
  2. desfaça o tempering em cada uma e obtenha as 624 palavras do estado;
  3. carregue o estado num gerador novo, com random.setstate((3, tuple(estado) + (624,), None));
  4. peça os próximos números: são os mesmos que a vítima vai receber.
o gerador da vítima estado interno s[0] … s[623] 624 números de 32 bits tempering saídas y[0] … y[623] as próximas y[624] y[625] … 1 junte 624 saídas o que você juntou y[0] … y[623] 2 desfaz o tempering estado recuperado s[0] … s[623] 3 setstate seu gerador prevê y[624] y[625] … 4 iguais
Com 624 saídas seguidas, desfazer o tempering devolve o estado interno; carregado com setstate num gerador novo, ele produz os mesmos próximos números que a vítima vai receber.

Por isso a documentação do Python avisa que o random não deve ser usado para segurança. Senhas, tokens, sais e chaves precisam de um gerador criptográfico, como o módulo secrets ou os.urandom, que não deixa reconstruir o estado a partir das saídas.

Num CTF, desconfie de qualquer lista com exatamente 624 números de 32 bits: é o estado inteiro de um Mersenne Twister.

Aparece nestes desafios