Iniciante Criptografia

Erros comuns de criptografia

Usar criptografia não garante segurança. Implementações incorretas criam uma falsa sensação de proteção enquanto deixam dados expostos. Estes são os erros mais comuns.

Erro 1: modo ECB (Electronic Codebook)

No modo ECB, cada bloco de dados é cifrado independentemente com a mesma chave. Blocos iguais geram blocos cifrados iguais.

Dado:    [BLOCO_A][BLOCO_A][BLOCO_B]
ECB:     [CIFRA_A][CIFRA_A][CIFRA_B]
         ^--- padrão visível ---^

Isso vaza estrutura do dado original. O exemplo clássico: cifrar uma imagem bitmap com AES-ECB — a silhueta permanece visível.

Solução: use CBC com IV aleatório, ou melhor, AES-GCM.

from Crypto.Cipher import AES

# Errado
cipher = AES.new(key, AES.MODE_ECB)

# Correto
import os
iv = os.urandom(16)
cipher = AES.new(key, AES.MODE_CBC, iv)

Erro 2: IV reutilizado

CBC e CTR requerem um IV (vetor de inicialização) único por mensagem. Reutilizar o mesmo IV com a mesma chave quebra a confidencialidade.

Em modo CTR, dois textos cifrados com mesmo IV e chave permitem XOR entre eles, revelando os dados.

C1 = M1 ⊕ keystream
C2 = M2 ⊕ keystream (mesmo IV → mesmo keystream)
C1 ⊕ C2 = M1 ⊕ M2  ← estrutura das mensagens fica exposta

Solução: gere IV aleatório com os.urandom(16) a cada cifração. Armazene o IV junto ao ciphertext (ele não precisa ser secreto).

Erro 3: chave hardcoded

# Jamais faça isso
KEY = b"minha_chave_fixa_1234567890abcdef"

def cifrar(dado):
    cipher = AES.new(KEY, AES.MODE_GCM)
    return cipher.encrypt(dado)

A chave no código-fonte vaza via repositório git, logs, binários descompilados. Uma chave comprometida compromete todos os dados históricos.

Solução: carregue a chave de variável de ambiente ou de um serviço de segredos.

import os
KEY = os.environ["APP_ENCRYPTION_KEY"].encode()
# Ou use AWS Secrets Manager, HashiCorp Vault, etc.

Erro 4: cifrar sem autenticar

AES-CBC cifra, mas não garante integridade. Um atacante pode alterar o ciphertext e a decifração vai produzir lixo ou, pior, um valor controlado (bit-flipping attack).

Cifrado original: [...][TARGET_BLOCO][...]
Atacante inverte bit no bloco anterior → altera TARGET_BLOCO após decifração

Solução: use modos autenticados — AES-GCM ou AES-CCM. Eles combinam cifração + autenticação em uma operação.

from Crypto.Cipher import AES
import os

key = os.urandom(32)
nonce = os.urandom(16)
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
ciphertext, tag = cipher.encrypt_and_digest(b"dado sensivel")
# tag verifica integridade na decifração

Erro 5: número aleatório fraco

Não use random do Python ou rand() do C para gerar chaves ou IVs. Esses geradores são pseudoaleatórios e não são seguros criptograficamente.

# Errado
import random
key = random.randbytes(32)

# Correto
import os
key = os.urandom(32)

Resumo dos erros

ErroConsequênciaFix
Modo ECBVaza padrõesUse GCM ou CBC com IV
IV reutilizadoQuebra confidencialidadeIV aleatório por mensagem
Chave hardcodedExposição via códigoVariável de ambiente/vault
Sem autenticaçãoBit-flipping attackUse AES-GCM
PRNG fracoChave previsívelUse os.urandom()