Pular para conteúdo

Projeto 13: Gestão e Armazenamento Seguro de Senhas com Argon2id 🗝️

Escopo do Projeto

Objetivo: Desenvolver um subsistema completo para armazenamento de credenciais de usuários utilizando a função de derivação de chaves com memória rígida Argon2id (vencedora do Password Hashing Competition e padrão RFC 9106).


🎯 1. Contexto & Desafio Prático

Algoritmos clássicos de hash como MD5 e SHA-1 são completamente inadequados para armazenamento de senhas, e até mesmo SHA-256 é vulnerável a ataques massivos de quebra por GPU. Você projetará uma biblioteca de armazenamento de senhas de última geração configurando custo de memória, tempo e paralelismo com Argon2id, incluindo suporte a rehash transparente.


📋 2. Requisitos Técnicos Obrigatórios

  • R1 (Configuração dos Parâmetros de Custo): Configurar Argon2id com custo de memória de 64 MB (65536 KiB), tempo de 3 iterações e paralelismo de 4 threads, respeitando as recomendações oficiais da OWASP.
  • R2 (Geração e Incorporação de Salt Criptográfico): Gerar salt criptograficamente aleatório de 16 bytes para cada credencial gerada, impedindo ataques via Rainbow Tables.
  • R3 (Verificação em Tempo Constante): Realizar a conferência de hashes prevenindo ataques de temporização (Timing Attacks) por meio de comparação segura de bytes.
  • R4 (Mecanismo de Upgrade e Rehash Automático): Identificar no momento do login quando uma senha foi cifrada com algoritmo legado ou parâmetros obsoletos e reexecutar o hash de forma transparente.

📐 3. Diagrama Conceitual & Arquitetura

flowchart TD
    Login["Tentativa de Login (Usuário e Senha)"] --> Fetch["Buscar Registro do Usuário no DB"]
    Fetch --> Verify{"Verificação Argon2id em Tempo Constante"}
    Verify -- Inválida --> Reject["Rejeitar com HTTP 401 (Atraso Constante)"]
    Verify -- Válida --> CheckCost{"Parâmetros de Custo Atualizados?"}
    CheckCost -- Sim --> Success["Gerar Sessão / JWT Seguro"]
    CheckCost -- Não (Hash Legado) --> Rehash["Gerar Novo Hash Argon2id Atualizado"]
    Rehash --> SaveDB["Atualizar Registro no Banco sem Pedir Troca ao Usuário"]
    SaveDB --> Success
    style Login fill:#e1f5fe,stroke:#01579b
    style Verify fill:#fff3e0,stroke:#e65100
    style Success fill:#e8f5e9,stroke:#2e7d32
    style Reject fill:#ffebee,stroke:#c62828

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

// argon2_password_manager.py
import secrets
import hashlib
import hmac

class MockArgon2idManager:
    """Simulação educacional da mecânica de salt + memória/tempo do Argon2id (RFC 9106)."""
    def __init__(self, memory_cost_kib: int = 65536, time_cost: int = 3, parallelism: int = 4):
        self.memory_cost = memory_cost_kib
        self.time_cost = time_cost
        self.parallelism = parallelism

    def hash_password(self, password: str) -> str:
        # Salt criptográfico de 128 bits
        salt = secrets.token_bytes(16)

        # Derivação simulada aplicando múltiplas rodadas dependentes
        current = hashlib.sha256(salt + password.encode('utf-8')).digest()
        for _ in range(self.time_cost * 1000):
            current = hashlib.sha256(current + salt).digest()

        salt_hex = salt.hex()
        hash_hex = current.hex()
        return f"$argon2id$v=19$m={self.memory_cost},t={self.time_cost},p={self.parallelism}${salt_hex}${hash_hex}"

    def verify_password(self, password: str, encoded_hash: str) -> bool:
        parts = encoded_hash.split('$')
        if len(parts) < 6 or parts[1] != 'argon2id':
            return False
        salt_hex = parts[4]
        target_hash = parts[5]

        salt = bytes.fromhex(salt_hex)
        current = hashlib.sha256(salt + password.encode('utf-8')).digest()
        for _ in range(self.time_cost * 1000):
            current = hashlib.sha256(current + salt).digest()

        # Comparação em tempo constante contra Timing Attacks
        return hmac.compare_digest(current.hex(), target_hash)

if __name__ == '__main__':
    pwd_mgr = MockArgon2idManager()
    minha_senha = "SenhaForteCorporativa@2026!"
    hash_gerado = pwd_mgr.hash_password(minha_senha)
    print(f"Hash seguro formatado: {hash_gerado}")
    assert pwd_mgr.verify_password(minha_senha, hash_gerado) is True
    assert pwd_mgr.verify_password("SenhaIncorreta", hash_gerado) is False
    print("Mecanismo de senhas Argon2id validado com sucesso!")

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

  1. Implementação de parâmetros de custo de memória, iterações e paralelismo.
  2. Geração de salteamento aleatório independente por usuário.
  3. Comparação segura de hashes em tempo constante imune a ataques de temporização.