Disciplina: Segurança Computacional — UnB
Professor: Prof. Roberto Rodrigues Filho
Grupo: 4 integrantes
Implementação didática do protocolo Kerberos utilizando exclusivamente criptografia de chave simétrica. O sistema é composto por quatro componentes que implementam o fluxo completo de autenticação:
- Authentication Server (AS) — emite o Ticket Granting Ticket (TGT)
- Ticket Granting Server (TGS) — valida o TGT e emite o Service Ticket
- Serviço Protegido — valida o Service Ticket, realiza autenticação mútua e gerencia notas por usuário
- Cliente — orquestra o fluxo AS → TGS → Serviço
CLIENTE AS TGS SERVIÇO
│ │ │ │
├── MSG_AUTH_REQUEST ───►│ │ │
│ "alice" │ │ │
│ │ Deriva chave da senha │ │
│ │ Gera K_c_AS │ │
│ │ Monta TGT cifrado │ │
│◄── MSG_AUTH_REPLY ─────┤ │ │
│ TGT || K_c_AS_cif │ │ │
│ │ │ │
├── MSG_TGS_REQUEST ─────► │ │
│ TGT || "notas" │ │
│ │ Decifra TGT │
│ │ Verifica validade │
│ │ Gera K_c_svc │
│ │ Monta SvcTicket │
│◄── MSG_TGS_REPLY ────────────────────────────────┤ │
│ SvcTicket || K_c_svc_cif │
│ │
├── MSG_SVC_REQUEST ─────────────────────────────────────────────────────►│
│ SvcTicket || Authenticator_cif │
│ │ Decifra ticket
│ │ Decifra authenticator
│ │ Verifica nome + timestamp
│ │ Verifica expiração
│◄── MSG_SVC_REPLY ──────────────────────────────────────────────────────┤ Soma 1 no timestamp
│ timestamp+1 cifrado │ Cifra e envia
│ │
│ Verifica timestamp+1 │
│ -> Autenticação mútua OK! │
│ │
├── MSG_NOTE_* ──────────────────────────────────────────────────────────►│
│ /notas, /ler, /escrever │ Lista, lê ou salva nota
│◄── MSG_NOTE_REPLY ─────────────────────────────────────────────────────┤
│ conteúdo da nota / confirmação │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Cada comando abre NOVA conexão TCP, reutilizando o mesmo │ │
│ │ Service Ticket (Single Sign-On). │ │
│ └─────────────────────────────────────────────────────────────┘ │
Execute uma vez no diretório raiz do projeto:
python3 -m venv .venv
source .venv/bin/activate
pip install -e . # ← passo crítico: instala dependências e entrypointsO pip install -e . instala o pacote em modo editável e registra os comandos
gerar-chaves, kerberos-servidor, kerberos-cliente, etc.
# Terminal 1 — gerar chaves e iniciar servidores
source .venv/bin/activate
gerar-chaves # gera keys/as_master.key e keys/service_master.key (16 bytes)
kerberos-servidor # AS + TGS + Serviço em threads (Ctrl+C para parar)# Terminal 2 — cliente
source .venv/bin/activate
kerberos-clienteO cliente exibe um menu:
1. Cadastrar usuario
2. Fazer login
0. Sair
A opção 1 registra um novo usuário e retorna ao menu (dispensa cadastrar-usuario manual).
A opção 2 inicia o fluxo Kerberos (AS → TGS → Serviço) e abre o terminal de notas.
source .venv/bin/activate
python -m pytest tests/ -vExpandir
# Cadastrar usuário manualmente (sem abrir o cliente)
cadastrar-usuario
# Iniciar cada servidor em terminais separados
as-server # AS (porta 5450)
tgs-server # TGS (porta 5451)
service-server # Serviço (porta 5452)
# Testes de ataque (requer servidores rodando)
simular-ataque # 4 cenários de ataquekerberos-chat/
│
├── common/ ← Código compartilhado (todos usam)
│ ├── config.py # Portas, hosts, constantes, caminhos de chave
│ ├── crypto.py # AES-GCM, PBKDF2
│ └── protocol.py # Re-exporta tgs_server/message.py
│
├── as_server/ ← Authentication Server
│ ├── as_server.py # Servidor TCP que emite TGTs
│ └── user_db.py # Banco de usuários (JSON)
│
├── tgs_server/ ← Ticket Granting Server
│ ├── message.py # Empacotar/desempacotar, tipos, tickets
│ └── tgs_server.py # Valida TGT, emite Service Ticket
│
├── service/ ← Serviço Protegido
│ └── service_server.py # Valida Service Ticket + gerencia notas
│
├── client/ ← Cliente
│ ├── client.py # Orquestra fluxo Kerberos + menu cadastro/login
│ └── ui.py # Stub: interface de terminal
│
├── keys/ ← Chaves mestras (geradas com gerar-chaves)
│ ├── as_master.key
│ └── service_master.key
│
├── data/ ← Dados de usuários (runtime)
│ └── user_db.json # {"users": {"nome": {"salt": hex, "hash_chave": hex}}}
│
├── docs/
│ ├── issues_projeto.md # 40 tarefas (issues) do projeto
│ ├── issues_pendentes.md # Issues de auditoria e correções
│ ├── plano_servidor_notas.md # Design do serviço de notas
│ ├── servico_notas.md # Por que substituímos o chat relay pelo serviço de notas
│ ├── plano_apresentacao_bloco3.md # Roteiro da apresentação — Bloco 3
│ └── planejamento.md # Divisão de tarefas, relatório, vídeo
│
├── scripts/
│ ├── gerar_chaves.py # Gera as chaves mestras
│ ├── cadastrar_usuario.py # Adiciona usuário ao JSON
│ ├── kerberos_demo.py # Lança os 3 servidores em threads
│ └── simular_ataque.py # 4 cenários de ataque (requer servidores)
│
├── tests/ ← Testes unitários (pytest, 106 testes)
│ ├── conftest.py # Fixtures compartilhadas
│ ├── test_cadastrar_usuario.py
│ ├── test_config.py
│ ├── test_crypto.py
│ ├── test_gerar_chaves.py
│ ├── test_message.py
│ ├── test_tgs_server.py
│ ├── test_user_db.py
│ └── test_as_server_e2e.py # Testes de integração do AS
│
├── pyproject.toml # Configuração do projeto + entry-points
├── .gitignore
└── README.md
| Componente | Tecnologia | Por quê |
|---|---|---|
| Linguagem | Python 3 | Todos conhecem |
| Criptografia simétrica | AES-128-GCM (cryptography) |
Cifra + autentica em 1 operação |
| Derivação de chave | PBKDF2-HMAC-SHA256 (cryptography) |
Nativo, bem documentado, 100.000 iterações |
| Serialização | struct.pack / struct.unpack |
Binário, sem dependências externas |
| Rede | socket TCP puro |
Simples, didático |
| Concorrência | threading.Thread |
Servidores atendem múltiplos clientes |
| Banco de usuários | JSON (user_db.json) |
Arquivo texto, sem banco de dados |
| Interface | Terminal (input() / print()) |
Sem GUI, mínimo viável |
- Cifra simétrica autenticada (confidencialidade + integridade)
- Nonce de 12 bytes aleatório a cada operação
- Uma única chamada = cifra + tag de autenticação
- Deriva uma chave de 16 bytes a partir de senha + salt
- 100.000 iterações para dificultar ataques de força bruta
- Salt único de 16 bytes por usuário
| Servidor | Host | Porta |
|---|---|---|
| Authentication Server (AS) | 127.0.0.1 | 5450 |
| Ticket Granting Server (TGS) | 127.0.0.1 | 5451 |
| Serviço Protegido | 127.0.0.1 | 5452 |
Toda mensagem trafega na rede com um cabeçalho de 6 bytes seguido do payload:
[2 bytes] tipo da mensagem (unsigned short, big-endian)
[4 bytes] tamanho do payload em bytes (unsigned int, big-endian)
[N bytes] payload (o conteúdo em si)
Esse cabeçalho é montado pela função empacotar() em common/protocol.py.
| # | Constante | Origem → Destino | Payload |
|---|---|---|---|
| 1 | MSG_AUTH_REQUEST |
Cliente → AS | nome_usuario (bytes) |
| 2 | MSG_AUTH_REPLY |
AS → Cliente | salt(16) + [4B tam_tgt][TGT_cif] + [4B tam_k][K_c_AS_cif] |
| 3 | MSG_TGS_REQUEST |
Cliente → TGS | [4B tam_tgt][TGT][4B tam_svc][nome] |
| 4 | MSG_TGS_REPLY |
TGS → Cliente | [4B tam_st][ST][4B tam_ks][K_c_svc] |
| 5 | MSG_SVC_REQUEST |
Cliente → Serviço | [4B tam_st][ST][4B tam_auth][authenticator] |
| 6 | MSG_SVC_REPLY |
Serviço → Cliente | timestamp+1 cifrado(12+8) |
| 7 | MSG_CHAT |
(legado) | — |
| 8 | MSG_ECHO |
(legado) | — |
| 9 | MSG_ERROR |
Qualquer → Qualquer | mensagem de erro (bytes) |
| 10 | MSG_NOTE_LIST |
Cliente → Serviço | (vazio) |
| 11 | MSG_NOTE_READ |
Cliente → Serviço | nome_do_arquivo (bytes) |
| 12 | MSG_NOTE_WRITE |
Cliente → Serviço | nome_arquivo\n<conteudo> (bytes) |
| 13 | MSG_NOTE_REPLY |
Serviço → Cliente | conteúdo ou confirmação (bytes) |
| 14 | MSG_NOTE_DELETE |
Cliente → Serviço | nome_do_arquivo (bytes) |
(12+*)= nonce AES-GCM (12 bytes) + ciphertext de tamanho variável
(12+8)= nonce (12 bytes) + ciphertext de 8 bytes (apenas um timestamp)
[4B tam]= prefixo de 4 bytes (unsigned int, big-endian) indicando tamanho do blob seguinte
- MSG_TGS_REQUEST e MSG_TGS_REPLY: blocos de tamanho variável (TGT, Service Ticket, chave de sessão) são sempre precedidos por um prefixo de 4 bytes com seu comprimento.
- MSG_SVC_REQUEST: mesma lógica — Service Ticket e authenticator têm prefixos de 4 bytes.
- MSG_AUTH_REPLY: contém salt de 16 bytes no início, seguido por dois blocos cifrados independentemente — o TGT (cifrado com
as_master_key) e K_c_AS (cifrada com a chave derivada da senha do usuário). Cada bloco cifrado tem prefixo de 4 bytes com seu tamanho. - MSG_SVC_REQUEST: o authenticator é a estrutura
{nome_usuario(2+*) + timestamp(8)}cifrada comK_c_svc. - MSG_SVC_REPLY: o timestamp do authenticator +1, cifrado com
K_c_svc— prova que o serviço conhece a chave (autenticação mútua). - O
nome_servicoemMSG_TGS_REQUESTé um identificador simples em bytes (ex:b"notas",b"chat"). - MSG_NOTE_LIST: payload vazio — o ticket já identifica o usuário.
- MSG_NOTE_READ: payload contém apenas o nome do arquivo a ser lido.
- MSG_NOTE_WRITE: a primeira linha do payload é o nome do arquivo; o resto é o conteúdo a salvar.
Para planejamento da equipe (divisão de tarefas, relatório, vídeo), veja
docs/planejamento.md.
O design detalhado do serviço de notas está emdocs/plano_servidor_notas.md.
A justificativa da substituição do chat relay pelo serviço de notas está emdocs/servico_notas.md.