Pular para conteúdo

Projeto 04: Criptografia Simétrica de Bloco: AES-CBC vs AES-GCM 🔒

Escopo do Projeto

Objetivo: Implementar cifragem de arquivos com o padrão AES de 256 bits, analisando os riscos de vazamento e ataques de padding oracle no modo CBC e dominando a integridade autenticada no modo moderno GCM (AEAD).


🎯 1. Contexto & Desafio Prático

A cifragem de dados em repouso exige a escolha correta do modo de operação de cifras de bloco. Você construirá uma ferramenta de terminal de cifragem e decifragem de arquivos sensíveis com AES-256, demonstrando por que o modo GCM impede adulterações de bits que passavam despercebidas no modo CBC.


📋 2. Requisitos Técnicos Obrigatórios

  • R1 (Implementação com AES-256-GCM): Utilizar chave de 256 bits gerada com CSPRNG e Nonce criptograficamente único de 96 bits (12 bytes).
  • R2 (Demonstração do Falha do CBC): Demonstrar o ataque de manipulação de bits (Bit-Flipping Attack) no modo CBC sem detecção de corrupção.
  • R3 (Validação da Tag de Autenticação em GCM): Comprovar que qualquer alteração de 1 bit no arquivo cifrado em GCM gera rejeição imediata com exceção InvalidTag.
  • R4 (CLI de Cifragem de Arquivos): Construir utilitário CLI: secure-vault encrypt <file> -k <key> e secure-vault decrypt <file> -k <key>.

📐 3. Diagrama Conceitual & Arquitetura

graph TD
    File["Arquivo Confidencial"] --> Nonce["Nonce Único (12 Bytes)"]
    File & Nonce --> AESGCM["Cifra AES-256-GCM (AEAD)"]
    Key["Chave de 256 bits"] --> AESGCM
    AESGCM --> Encrypted["Envelope Cifrado [Nonce + Ciphertext + AuthTag]"]
    Encrypted --> Attack{"Atacante adultera 1 bit no disco"}
    Attack --> DecryptFail["Decifragem rejeitada: Tag Inválida! Integridade Garantida."]
    style File fill:#e1f5fe,stroke:#01579b
    style AESGCM fill:#fff3e0,stroke:#e65100
    style Encrypted fill:#e8f5e9,stroke:#2e7d32
    style DecryptFail fill:#ffebee,stroke:#c62828

💻 4. Especificação Técnica & Código de Referência

// aes_vault_cli.py
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

def encrypt_file(filepath: str, key: bytes, output_path: str):
    with open(filepath, 'rb') as f:
        plaintext = f.read()
    aesgcm = AESGCM(key)
    nonce = os.urandom(12)
    ciphertext = aesgcm.encrypt(nonce, plaintext, None)
    with open(output_path, 'wb') as f:
        f.write(nonce + ciphertext)
    print(f"Arquivo cifrado com sucesso em: {output_path}")

def decrypt_file(filepath: str, key: bytes, output_path: str):
    with open(filepath, 'rb') as f:
        data = f.read()
    nonce, ciphertext = data[:12], data[12:]
    aesgcm = AESGCM(key)
    plaintext = aesgcm.decrypt(nonce, ciphertext, None) # Lança InvalidTag se violado
    with open(output_path, 'wb') as f:
        f.write(plaintext)
    print(f"Arquivo decifrado e verificado com sucesso em: {output_path}")

📦 5. Critérios de Avaliação e Entrega

  1. Cifragem e decifragem de arquivos executando sem erros em AES-256-GCM.
  2. Teste de corrupção intencional de bytes comprovando a rejeição pelo GCM.
  3. Utilização estrita de vetores de inicialização de alta entropia sem repetição.