Chave previsível
Uma chave de 128 bits tirada de algo previsível só tem tantas possibilidades quanto a sua origem; chave boa vem do sorteio do sistema.
A força do AES-128 vem de um número: existem cerca de 3,4 × 10³⁸ chaves possíveis (2 elevado a 128), e quem ataca sem pistas teria de testar quase todas. Mas essa conta só vale se a chave foi sorteada entre todas, cada uma com a mesma chance. Se a chave sai de algo previsível, o atacante não ataca o AES: ele testa as possibilidades da origem.
Um exemplo trabalhado. Um programa de backup tira a chave do relógio, para ninguém precisar guardá-la:
import hashlib, time
agora = str(int(time.time())) # por exemplo '1773500000'
chave = hashlib.sha256(agora.encode()).digest()[:16] # 16 bytes: AES-128
time.time() devolve o tempo Unix, os segundos passados desde 1º de janeiro de 1970; 1773500000 é 14 de março de 2026, às 14:53:20 no horário UTC. A chave que sai do SHA-256 tem 16 bytes de aparência perfeitamente aleatória. Mas o arquivo cifrado tem data de modificação, e quem sabe em que dia o backup rodou tem só 86.400 candidatos, um para cada segundo do dia. O Python testa todos em menos de um segundo.
O hash não ajuda: ele embaralha, mas não multiplica. 86.400 entradas diferentes dão 86.400 chaves diferentes, nem uma a mais. O que conta é quantos valores a origem pode ter, e isso se mede em bits: o expoente de 2 que chega a esse número (365 fica perto de 2 elevado a 8,5). Cada bit a mais dobra o trabalho de quem ataca.
| De onde vem a chave | Chaves possíveis | Bits |
|---|---|---|
| Data do dia, num ano conhecido | 365 | cerca de 8,5 |
| PIN de 4 dígitos | 10.000 | cerca de 13 |
| Segundo do relógio, num dia conhecido | 86.400 | cerca de 16 |
os.urandom(16) |
3,4 × 10³⁸ | 128 |
Para saber qual candidato é o certo, o atacante procura no texto decifrado algo que já espera ver: um cabeçalho conhecido, a assinatura de um tipo de arquivo ou um preenchimento válido (com a chave errada, o unpad quase sempre dá erro).
O mesmo vale para o módulo random do Python: ele é um gerador pseudoaleatório, feito para simulações e jogos, e quem descobre a semente (muitas vezes, o relógio) refaz a sequência inteira (conceito Semente de números pseudoaleatórios).
O uso correto.
- A chave sai do gerador criptográfico do sistema operacional, alimentado por eventos imprevisíveis do hardware:
os.urandom(16)ousecrets.token_bytes(16)no Python,openssl rand -hex 16no terminal. - A chave sorteada é guardada (num arquivo que só o programa lê, num cofre de chaves), e não recalculada a partir de algo que outros sabem.
- Quando a chave precisa vir de uma senha, ela passa por uma derivação lenta e com sal, como o PBKDF2, o scrypt ou o Argon2 (conceito Derivação de chave), e a senha precisa ser longa: a derivação deixa cada tentativa mais cara, mas não aumenta o número de senhas possíveis.