Pular para conteúdo

Projeto 10: Cofre de Segredos e Envelope Encryption em Python 🐍

Escopo do Projeto

Objetivo: Construir um módulo em Python para gerenciamento de dados confidenciais em repouso empregando a arquitetura de Criptografia em Envelope (Envelope Encryption) com AES-256-GCM.


🎯 1. Contexto & Desafio Prático

Em plataformas de nuvem e sistemas de alta escala, criptografar grandes volumes de dados diretamente com uma chave mestra (KEK) gera gargalos e riscos catastróficos em caso de comprometimento da chave. Você implementará o padrão industrial de Envelope Encryption, gerando chaves de dados efêmeras (DEK) para cada registro e encapsulando-as com uma chave mestra de alta segurança.


📋 2. Requisitos Técnicos Obrigatórios

  • R1 (Geração de Chaves de Dados - DEK): Implementar a geração segura de chaves efêmeras de 256 bits com secrets.token_bytes(32) para cada operação de escrita.
  • R2 (Cifragem de Dados com AES-GCM): Cifrar a carga útil de dados usando AES-256-GCM com IV único de 96 bits gerado pelo sistema operacional e coletar a tag de autenticação.
  • R3 (Encapsulamento da DEK com KEK Mestra): Cifrar a DEK efêmera utilizando a chave mestra de criptografia (Key Encryption Key) protegida em memória.
  • R4 (Decifragem e Validação de Adulteração): Construir a rotina inversa que decifra a DEK, valida a tag de autenticação dos dados e rejeita imediatamente payloads violados.

📐 3. Diagrama Conceitual & Arquitetura

graph TD
    Data["Dados do Usuário (Plaintext)"] -->|Cifra AES-256-GCM| EncData["Ciphertext dos Dados"]
    DEK["Chave de Dados Efêmera (DEK - 256 bits)"] -->|Cifra o Dado| EncData
    DEK -->|Cifrada pela KEK| EncDEK["DEK Envelopada (Cifrada)"]
    KEK["Chave Mestra (KEK - Armazenada em Vault/HSM)"] -->|Protege a DEK| EncDEK
    EncData --> Envelope["Envelope Final (Payload JSON com IV, Tag, DEK Cifrada e Dados)"]
    EncDEK --> Envelope
    style Data fill:#e1f5fe,stroke:#01579b
    style DEK fill:#fff3e0,stroke:#e65100
    style KEK fill:#f3e5f5,stroke:#7b1fa2
    style Envelope fill:#e8f5e9,stroke:#2e7d32

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

// envelope_vault.py
import os
import json
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

class EnvelopeVault:
    def __init__(self, master_kek: bytes):
        if len(master_kek) != 32:
            raise ValueError("A KEK mestra deve possuir exatamente 256 bits (32 bytes).")
        self.kek_cipher = AESGCM(master_kek)

    def encrypt_envelope(self, plaintext: bytes) -> str:
        # 1. Gerar DEK efêmera de 256 bits
        dek = os.urandom(32)

        # 2. Cifrar o dado com a DEK via AES-GCM
        data_nonce = os.urandom(12)
        data_cipher = AESGCM(dek)
        ciphertext = data_cipher.encrypt(data_nonce, plaintext, None)

        # 3. Cifrar a DEK com a KEK mestra
        kek_nonce = os.urandom(12)
        encrypted_dek = self.kek_cipher.encrypt(kek_nonce, dek, None)

        # 4. Montar o envelope estruturado
        envelope = {
            "kek_nonce": base64.b64encode(kek_nonce).decode('utf-8'),
            "encrypted_dek": base64.b64encode(encrypted_dek).decode('utf-8'),
            "data_nonce": base64.b64encode(data_nonce).decode('utf-8'),
            "ciphertext": base64.b64encode(ciphertext).decode('utf-8')
        }
        return json.dumps(envelope)

    def decrypt_envelope(self, envelope_json: str) -> bytes:
        data = json.loads(envelope_json)
        kek_nonce = base64.b64decode(data["kek_nonce"])
        encrypted_dek = base64.b64decode(data["encrypted_dek"])
        data_nonce = base64.b64decode(data["data_nonce"])
        ciphertext = base64.b64decode(data["ciphertext"])

        # Recuperar a DEK original decifrando com a KEK
        dek = self.kek_cipher.decrypt(kek_nonce, encrypted_dek, None)

        # Decifrar os dados confidenciais
        data_cipher = AESGCM(dek)
        return data_cipher.decrypt(data_nonce, ciphertext, None)

if __name__ == '__main__':
    master_key = os.urandom(32)
    vault = EnvelopeVault(master_key)
    msg = b"Dados Confidenciais de Pagamento: Cartao 4532-XXXX-XXXX-8910"
    pack = vault.encrypt_envelope(msg)
    recovered = vault.decrypt_envelope(pack)
    assert recovered == msg
    print("Envelope Encryption validado com sucesso. Dados decifrados com integridade!")

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

  1. Arquitetura de duas camadas com separação clara de DEK efêmera e KEK mestra.
  2. Uso estrito de cifras autenticadas (AES-256-GCM) sem reuso de IVs.
  3. Payload serializado em JSON com campos codificados em Base64 e validação de tampering.