🔐 AChave - Password Manager
Una bóveda de contraseñas moderna, segura y de código abierto. AChave es un gestor de contraseñas con cifrado cliente-servidor que permite almacenar y gestionar tus contraseñas de forma segura con interfaces web, desktop y extensión de navegador.
Desarrollado por Miguel Garcia, Ou Zhang y Borja Barroso durante el HackUDC 2026.
📋 Tabla de Contenidos
- Características
- Arquitectura
- Guía de Instalación
- Uso del Proyecto
- Flujo de Autenticación
- Sistema de Encriptación
- Base de Datos
- API Endpoints
- Estructura del Proyecto
- Contribución
- Licencia
✨ Características
- 🔐 Cifrado End-to-End: Las contraseñas se cifran en el cliente con criptografía RSA + AES
- 👤 Autenticación Multi-fase: Registro → Verificación email → Setup Master Password
- 🗂️ Múltiples Bóvedas: Organiza tus contraseñas en diferentes cofres temáticos
- 📱 Multiplataforma: Web (Next.js), Frontend Dashboard y Extensión Chrome
- 🔍 Validación de Seguridad: Integración con API de contraseñas comprometidas (HaveIBeenPwned)
- ⚡ Generador de Contraseñas: Genera contraseñas seguras y personalizadas
- 🎨 Interfaz Moderna: UI oscura/clara con TailwindCSS
- 🚀 Despliegue Containerizado: Docker Compose para ejecución local completa
🏗️ Arquitectura
graph TB
subgraph Frontend["Frontend (Next.js)"]
A1["Pages<br/>(Login, Dashboard, Claves)"]
A2["Components<br/>(Modals, Layout, Forms)"]
A3["Crypto Context<br/>(Manejo de llaves)"]
A4["Hooks<br/>(API, Encrypt, Validate)"]
end
subgraph Extension["Chrome Extension<br/>(Vite + React)"]
B1["React Components"]
B2["Content Script"]
B3["Background Script"]
B4["Storage API"]
end
subgraph Backend["Backend (FastAPI)"]
C1["Routers<br/>(Auth, Passwords, Vaults)"]
C2["CRUD Operations<br/>(User, Password, Vault)"]
C3["Security Utils<br/>(JWT, Bcrypt, Crypto)"]
C4["Email Service<br/>(Verification, Notifications)"]
end
subgraph Database["Database (PostgreSQL)"]
D1["Users Table"]
D2["Vaults Table"]
D3["Passwords Table"]
end
A1 --> A3
A1 --> A4
A2 --> A3
B1 --> B4
B2 --> B4
B3 --> B4
A4 -.->|HTTP Requests| C1
B4 -.->|HTTP Requests| C1
C1 --> C2
C1 --> C3
C1 --> C4
C2 --> Database
📦 Componentes Principales
Backend (FastAPI)
- Lenguaje: Python 3.10+
- Framework: FastAPI
- Base de Datos: PostgreSQL
- Autenticación: JWT (HS256)
- Encriptación: Bcrypt, RSA, AES
Frontend (Next.js)
- Lenguaje: TypeScript / React 19
- Estilos: TailwindCSS
- Encriptación: node-forge
- Estado: React Context
Extensión Chrome (Vite)
- Lenguaje: TypeScript / React
- Build Tool: Vite
- APIs: chrome.storage, chrome.tabs
🚀 Guía de Instalación
Requisitos Previos
- Docker & Docker Compose (recomendado para fácil setup)
- O alternativamente:
- Python 3.10+
- Node.js 18+
- PostgreSQL 15+
Opción 1: Con Docker Compose (⭐ Recomendado)
- Clonar el repositorio:
git clone https://github.com/tu-usuario/AChave.git
cd AChave
- Configurar variables de entorno:
cp backend/.env.example backend/.env
- Editar
backend/.envcon tus valores:
DATABASE_URL=postgresql://postgres@db:5432/achave_db
JWT_SECRET_KEY=tu-clave-secreta-super-segura-change-this
SMTP_USER=tu-usuario-brevo@gmail.com
SMTP_PASSWORD=tu-api-key-brevo
SMTP_FROM_EMAIL=noreply@achave.com
FRONTEND_URL=http://localhost:3000
- Iniciar con Docker Compose:
docker-compose up --build
Esto levantará:
- PostgreSQL en
localhost:5432 - Backend en
http://localhost:8000 - Frontend en
http://localhost:3000
- Acceder a la aplicación:
- Frontend: http://localhost:3000
- API Docs (Swagger): http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
Opción 2: Instalación Manual (Sin Docker)
Backend
- Navegar a la carpeta backend:
cd backend
- Crear entorno virtual:
python -m venv .venv
source .venv/bin/activate # En Windows: .venv\Scripts\activate
- Instalar dependencias:
pip install -e .
- Crear base de datos PostgreSQL:
createdb achave_db
- Configurar variables de entorno:
cp .env.example .env
# Editar .env con tus valores
- Iniciar el servidor:
bash uvicorn main:app --reload --host 0.0.0.0 --port 8000
Frontend
- Navegar a la carpeta frontend:
cd frontend
- Instalar dependencias:
npm install
- Crear archivo
.env.local:
NEXT_PUBLIC_API_URL=http://localhost:8000
- Iniciar servidor de desarrollo:
npm run dev
Accesible en: http://localhost:3000
Extensión Chrome
- Navegar a la carpeta extension:
cd extension
- Instalar dependencias:
npm install
- Build de la extensión:
npm run build
- Cargar en Chrome:
- Abrir
chrome://extensions/ - Activar "Modo de desarrollador"
- Click en "Cargar extensión sin empaquetar"
- Seleccionar la carpeta
extension/dist/
- Abrir
📖 Uso del Proyecto
Flujo de Usuario
- Registro: El usuario ingresa su email
- Verificación: Se envía un email de confirmación
- Setup Master Password: Después de verificar, configura su Master Password
- Dashboard: Acceso a bóvedas y contraseñas
- Gestión: Crear, editar, eliminar contraseñas y bóvedas
Comandos Útiles
# Backend - Reset completo de la base de datos
python reset_db.py
# Frontend - Build para producción
npm run build
# Extension - Build optimizado
npm run build
# Todos - Activar en modo desarrollo con Docker
docker-compose up -d
docker-compose logs -f
🔐 Flujo de Autenticación
sequenceDiagram
actor User
participant Frontend
participant Backend
participant Database
participant Email
User->>Frontend: 1. Ingresa email
Frontend->>Backend: POST /auth/register
Backend->>Database: Crear usuario (is_verified=false)
Backend->>Email: Enviar token de verificación
Email-->>User: Link de verificación
User->>Frontend: 2. Click link de verificación
Frontend->>Backend: GET /auth/verify/{token}
Backend->>Database: Marcar usuario como verified
Backend-->>Frontend: JWT temporal
User->>Frontend: 3. Configura Master Password + Keys
Frontend->>Frontend: Genera par de llaves RSA
Frontend->>Frontend: Cifra Master Password
Frontend->>Backend: POST /auth/setup-crypto
Backend->>Database: Hashear y guardar Master Password
Backend->>Database: Guardar llave pública y privada cifrada
Backend-->>Frontend: Usuario completamente setup
User->>Frontend: 4. Login
Frontend->>Backend: POST /auth/login (email + password)
Backend->>Database: Verificar credenciales con bcrypt
Backend->>Frontend: JWT + Paquete criptográfico
Frontend->>Frontend: Descargar llaves privadas en memoria
Frontend-->>User: ✅ Sesión iniciada
🔒 Sistema de Encriptación
AChave implementa un modelo híbrido de encriptación para máxima seguridad:
Componentes del Sistema
1. Master Password 🔑
- Contraseña principal del usuario
- Almacenada en backend: Hash bcrypt con salt (rounds=12)
- Usada en cliente: Clave de derivación para cifrar la llave privada RSA
- Algoritmo: Bcrypt HS256
2. Par de Llaves RSA 🔓
- Generadas en cliente durante setup (2048 bits)
- Llave Pública: Almacenada en texto plano en la BD
- Llave Privada: Cifrada con AES usando la Master Password
- Uso: Firma digital y validación de contraseñas
3. Validador Cifrado ✅
- Es
AES("SESAMO_ABIERTO", Master Password) - Propósito: Validar que la Master Password introducida en login es correcta
- Ventaja: No expone la contraseña en el servidor (zero-knowledge proof)
4. Contraseñas de Sitios Web 🌐
- Cifradas en cliente con AES-256-GCM
- Capa adicional: RSA encryption + AES encryption
- Almacenadas en BD: Como ciphertext opaco
- Descifrado: Solo en cliente con llaves privadas desencriptadas
Flujo de Cifrado Completo
graph LR
A["Master Password<br/>(Usuario ingresa)"]
B["Validador Cifrado<br/>AES SESAMO ABIERTO"]
C["Derivación de Clave"]
D["RSA 2048 Keys"]
E["Llave Privada<br/>Cifrada con AES"]
F["Contrasena Web"]
G["Cifra con AES"]
H["Base de Datos<br/>(ciphertext)"]
A --> B
B -.->|Validación| A
A --> C
C --> D
D --> E
E -->|Desencripta en cliente| D
F --> G
D --> G
G --> H
style B fill:#ff6b6b
style E fill:#4ecdc4
style H fill:#95e1d3
Ejemplo de Flujo Post-Login
1. Usuario ingresa: email + Master Password
2. Backend valida credenciales con bcrypt
3. Backend devuelve:
- JWT (para peticiones autenticadas)
- validador_cifrado (AES)
- llave_privada_cifrada (RSA privada, AES)
- llave_publica (RSA pública)
4. Frontend recibe todo y:
- Desencripta validador_cifrado con Master Password
- Verifica que el resultado sea "SESAMO_ABIERTO" ✓
- Desencripta llave_privada_cifrada con Master Password
- Guarda llaves en localStorage/sessionStorage
- Puede ahora decifrar contraseñas almacenadas
5. Cuando usuario solicita contraseña:
- Frontend envía petición a GET /passwords/{id}
- Backend devuelve ciphertext cifrado
- Frontend desencripta con RSA privada + AES
- Muestra contraseña al usuario
¿Por qué este modelo es seguro?
| Aspecto | Garantía |
|---|---|
| Master Password | Never sent to server (only hash) ✅ |
| Private Key | Protected by Master Password + AES ✅ |
| Passwords | Encrypted with RSA + AES, opaque in DB ✅ |
| Validation | Zero-knowledge proof (validador cifrado) ✅ |
| Token Hijacking | Sin llave privada, token es inútil ✅ |
🗄️ Base de Datos
Diagrama ER
erDiagram
USERS ||--o{ VAULTS : owns
VAULTS ||--o{ PASSWORDS : contains
USERS {
uuid user_id PK
string email UK
string hashed_password
boolean is_verified
text validador_cifrado
text llave_publica
text llave_privada_cifrada
string token_type
text access_token
timestamp timestamp
}
VAULTS {
uuid vault_id PK
string name
string description
string icon
string color
boolean is_default
uuid user_id FK
timestamp timestamp
}
PASSWORDS {
uuid passwords_id PK
string web
string user_email
text password
boolean compromised
uuid vault_id FK
}
Tablas Principales
USERS
CREATE TABLE users (
user_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
hashed_password VARCHAR(255), -- Bcrypt hash
is_verified BOOLEAN DEFAULT FALSE,
validador_cifrado TEXT, -- AES("SESAMO_ABIERTO", master_pwd)
llave_publica TEXT, -- RSA public key
llave_privada_cifrada TEXT, -- AES(RSA private key, master_pwd)
token_type VARCHAR(50),
access_token TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
VAULTS
CREATE TABLE vaults (
vault_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
description VARCHAR(255),
icon VARCHAR(255),
color VARCHAR(50),
is_default BOOLEAN DEFAULT FALSE,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
PASSWORDS
CREATE TABLE passwords (
passwords_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
vault_id UUID NOT NULL REFERENCES vaults(vault_id) ON DELETE CASCADE,
web VARCHAR(255) NOT NULL,
user_email VARCHAR(255) NOT NULL,
password TEXT NOT NULL, -- AES encrypted ciphertext
compromised BOOLEAN DEFAULT FALSE
);
📡 API Endpoints
Autenticación
| Método | Endpoint | Descripción |
|---|---|---|
POST |
/auth/register |
Registrar usuario (fase 1) |
GET |
/auth/verify/{token} |
Verificar email (fase 2) |
POST |
/auth/setup-crypto |
Setup Master Password + Keys (fase 3) |
POST |
/auth/login |
Login con email + password |
GET |
/auth/me |
Obtener perfil usuario |
POST |
/auth/logout |
Cerrar sesión |
Bóvedas
| Método | Endpoint | Descripción |
|---|---|---|
GET |
/vaults/ |
Listar bóvedas del usuario |
POST |
/vaults/ |
Crear nueva bóveda |
GET |
/vaults/{vault_id} |
Obtener detalles de bóveda |
PUT |
/vaults/{vault_id} |
Actualizar bóveda |
DELETE |
/vaults/{vault_id} |
Eliminar bóveda |
Contraseñas
| Método | Endpoint | Descripción |
|---|---|---|
GET |
/passwords/vault/{vault_id} |
Listar contraseñas de bóveda |
POST |
/passwords/ |
Crear contraseña |
GET |
/passwords/{password_id} |
Obtener detalles de contraseña |
PUT |
/passwords/{password_id} |
Actualizar contraseña |
DELETE |
/passwords/{password_id} |
Eliminar contraseña |
GET |
/passwords/check-pwned/{password} |
Validar vs HaveIBeenPwned |
🔐 Validación de Contraseñas Comprometidas
AChave integra la API de Have I Been Pwned (HIBP) para comparar las contraseñas guardadas y alertar al usuario si una contraseña ha sido comprometida en brechas de seguridad conocidas. El campo compromised se marca como true si la contraseña se encuentra en la base de datos de HIBP.
Ejemplo de Petición Autenticada
# Login
curl -X POST http://localhost:8000/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"MasterPassword123"}'
# Respuesta
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"validador_cifrado": "...",
"llave_privada_cifrada": "..."
}
# Usar token
curl -X GET http://localhost:8000/auth/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
📁 Estructura del Proyecto
AChave/
├── backend/ # FastAPI Backend
│ ├── main.py # Punto de entrada
│ ├── config.py # Configuración (env vars)
│ ├── database.py # Conexión PostgreSQL
│ ├── requirements.txt # Dependencias Python
│ ├── pyproject.toml # Setup del proyecto
│ ├── Dockerfile # Docker para backend
│ ├── models/ # ORM Models (SQLAlchemy)
│ │ ├── user.py
│ │ ├── vault.py
│ │ └── password.py
│ ├── schemas/ # Pydantic Schemas (validación)
│ │ ├── user.py
│ │ ├── vault.py
│ │ └── password.py
│ ├── crud/ # Database operations
│ │ ├── user.py
│ │ ├── vault.py
│ │ └── password.py
│ ├── routers/ # API Endpoints
│ │ ├── auth.py
│ │ ├── vaults.py
│ │ └── password.py
│ └── utils/ # Utilidades
│ ├── security.py # JWT, bcrypt, crypto
│ ├── email.py # SMTP (Brevo)
│ ├── oauth.py # OAuth (futuro)
│ └── hash_check.py # HaveIBeenPwned
│
├── frontend/ # Next.js Frontend
│ ├── src/
│ │ ├── app/ # App Router (pages)
│ │ │ ├── page.tsx # Home
│ │ │ ├── login/ # Login page
│ │ │ ├── verify/ # Email verification
│ │ │ └── (dashboard)/ # Protected routes
│ │ ├── components/ # React Components
│ │ │ ├── layout/ # Layout components
│ │ │ └── modals/ # Modal dialogs
│ │ ├── context/ # React Context
│ │ │ ├── CryptoContext.tsx
│ │ │ └── ThemeContext.tsx
│ │ ├── hooks/ # Custom React hooks
│ │ ├── lib/ # Utilidades
│ │ │ └── api.ts # API cliente
│ │ └── middleware.ts # NextAuth middleware
│ ├── package.json
│ ├── tsconfig.json
│ └── Dockerfile
│
├── extension/ # Chrome Extension
│ ├── src/
│ │ ├── App.tsx
│ │ ├── main.tsx
│ │ ├── components/ # React components
│ │ ├── pages/ # Extension pages
│ │ ├── context/ # Crypto context
│ │ ├── hooks/ # Custom hooks
│ │ └── lib/
│ │ ├── api.ts # API calls
│ │ └── storage.ts # chrome.storage API
│ ├── public/
│ │ ├── background.js # Service worker
│ │ ├── content.js # Content script
│ │ └── icons/ # Extension icons
│ ├── manifest.json # Extension manifest
│ └── vite.config.ts # Vite config
│
├── docker-compose.yml # Orquestación de servicios
├── README.md # Este archivo
└── LICENSE # Licencia
️ Troubleshooting
Problema: "Database connection refused"
Solución: Asegurate de que PostgreSQL está corriendo:
# Con Docker Compose
docker-compose ps
# O iniciar si está parado
docker-compose up db -d
Problema: "CORS error en frontend"
Solución: Verifica que el backend tiene CORS enabled y puertos correctos en main.py:
allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"]
Problema: "JWT token inválido"
Solución: Asegurate de cambiar JWT_SECRET_KEY en .env y que es diferente entre registros:
# Generar nueva clave
python -c "import secrets; print(secrets.token_urlsafe(32))"
Problema: "Email de verificación no recibido"
Solución: Configura credenciales SMTP en .env:
SMTP_USER=tu-usuario@gmail.com
SMTP_PASSWORD=tu-app-password
SMTP_FROM_EMAIL=noreply@tu-dominio.com
📚 Tecnologías Utilizadas
| Capa | Tecnología | Versión |
|---|---|---|
| Backend | FastAPI | 0.104+ |
| ORM | SQLAlchemy | 2.0+ |
| BD | PostgreSQL | 15+ |
| Auth | JWT (PyJWT) | 2.8+ |
| Crypto | bcrypt, cryptography | Latest |
| Frontend | Next.js | 16.1+ |
| React | React | 19+ |
| Estilos | TailwindCSS | 4+ |
| Crypto JS | node-forge | 1.3+ |
| Extension | Vite | 7+ |
🚀 Deployment
Deploy en Producción (Recomendado: Digital Ocean / Heroku)
- Variables de entorno en producción:
JWT_SECRET_KEY=super-clave-segura-generada
DATABASE_URL=postgresql://user:pass@prod-db.com/achave
FRONTEND_URL=https://tu-dominio.com
SMTP_USER=no-reply@tu-dominio.com
# ...más vars
- Build de Docker para producción:
docker build -t achave:latest .
docker push tu-registry/achave:latest
Configurar base de datos remota (managed PostgreSQL)
Enviar variables de entorno a plataforma de deployment
Deployar con docker-compose o Kubernetes
🤝 Contribución
¡Las contribuciones son bienvenidas! Por favor:
- Fork el repositorio
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
📝 Licencia
Este proyecto está bajo la licencia MIT - ver archivo LICENSE para detalles.
👥 Autores
- Miguel Garcia - Frontend & UI
- Ou Zhang - Backend
- Borja Barroso - Backend
Desarrollado durante HackUDC 2026 🏆
🔒 Security Policy
AChave es una bóveda de contraseñas, por lo que la seguridad es prioritaria:
- ✅ Todas las contraseñas se cifran cliente-side antes de enviar al servidor
- ✅ Master Password nunca se transmite al backend (solo hash)
- ✅ Llave privada está protegida con AES
- ✅ Validación con API de contraseñas comprometidas
- ⚠️ No somos responsables de pérdida de Master Password (es irrecuperable)
Última actualización: Marzo 2026 | v0.1.0
Built With
- fastapi
- haveibeenpwned
- nextjs
Log in or sign up for Devpost to join the conversation.