This content originally appeared on DEV Community and was authored by rventz
Escribo herramientas para no hacer las cosas aburridas dos veces, y últimamente lo he estado haciendo en lenguajes que nadie espera. Esta vez: Julia. Sí, ese lenguaje científico que todos asocian con matemáticas y machine learning. Si alguien está en desacuerdo solo grite.
Hace un par de semanas me di cuenta de algo: uso como 51 contraseñas diferentes (ok, son más), las guardo en un gestor comercial, y no tengo ni idea de qué tan "fuertes" son realmente. Así que decidí construir mi propio gestor de contraseñas que no solo almacene credenciales, sino que también me enseñe qué hace a una contraseña verdaderamente segura.
Spoiler: no es poner un "!" al final de tu nombre de mascota.
¿Por qué Julia y no lo obvio (Python/Go/Rust)?
Pregunta válida. Aquí está mi razonamiento:
- Performance nativa: Julia compila a código máquina vía LLVM. Para operaciones criptográficas intensivas (derivación de claves, hashing repetido), esto importa.
- Sintaxis expresiva: Puedo escribir matemáticas complejas (como cálculo de entropía) de forma que parece... matemáticas. No tengo que traducir fórmulas a código críptico.
-
Dispatch múltiple: Puedo definir diferentes comportamientos según el tipo de entrada sin convertir mi código en un zoológico de
if/else. - REPL interactivo: Desarrollo rápido, testeo en tiempo real, ajustes sobre la marcha.
Pero sobre todo: porque nadie lo espera. Y eso me gusta.
La Arquitectura: ¿Qué hace "profesional" a un gestor de contraseñas?
No quería hacer otro script de 40 líneas que codifique contraseñas en base64 y las llame "cifradas". Esto necesita ser real. Así que establecí requisitos mínimos:
Requisitos de seguridad:
- ✅ Cifrado real: Simulación de AES-256-GCM (en el demo uso XOR + derivación de claves, pero la estructura está lista para reemplazar con
Nettle.jl) - ✅ Derivación de claves: PBKDF2 con 100,000 iteraciones (preparado para Argon2)
- ✅ Salt único: Cada entrada cifrada usa su propio salt aleatorio criptográficamente seguro
- ✅ Zero-knowledge architecture: La contraseña maestra nunca se almacena, solo se deriva una clave de ella
- ✅ Generación segura: Uso de
Randomde Julia con fuentes criptográficamente seguras
Features funcionales:
- 🎲 Generador de contraseñas con opciones configurables
- 📊 Calculadora de entropía (la estrella del show)
- 💾 Almacenamiento cifrado en JSON
- 🔍 Comparador de contraseñas
- 🎨 Interfaz CLI intuitiva
El módulo de entropía: La parte interesante
Aquí es donde las cosas se ponen educativas. La mayoría de la gente piensa que P@ssw0rd! es segura porque tiene símbolos. Sorpresa: no lo es.
¿Qué es la entropía?
Entropía, en criptografía, es una medida de incertidumbre. Específicamente, cuántos bits de información impredecible contiene tu contraseña. Se calcula así:
H = L × log₂(R)
Donde:
- L = longitud de la contraseña
- R = tamaño del "pool" de caracteres posibles
Ejemplo visual:
Contraseña débil típica:
Password123!
- Longitud: 12 caracteres
- Pool detectado: minúsculas (26) + mayúsculas (26) + dígitos (10) + símbolos (32) = 94 caracteres
- Entropía: 12 × log₂(94) ≈ 78.5 bits
- Tiempo de cracking: ~95 años (GPU moderna)
Espera... ¿78 bits no es bueno? En teoría sí, PERO:
El problema real:
- Es una palabra del diccionario (
Password) - Patrón predecible (palabra + números + símbolo)
- Un ataque de diccionario la rompe en minutos, no años
Contraseña fuerte generada:
xK9#mL2$pQ7@vR4!nF
- Longitud: 18 caracteres
- Pool: 94 caracteres (uso completo del espacio)
- Entropía: 18 × log₂(94) ≈ 118 bits
- Tiempo de cracking: ~1.05 × 10¹⁶ años (prácticamente infinito)
Implementación en Julia
La función de cálculo de entropía es súper limpia:
function calculate_entropy(password::String)::Float64
if isempty(password)
return 0.0
end
# Detectar el pool de caracteres usado
has_lowercase = any(c -> islowercase(c), password)
has_uppercase = any(c -> isuppercase(c), password)
has_digits = any(c -> isdigit(c), password)
has_special = any(c -> !isalnum(c) && !isspace(c), password)
# Calcular tamaño del pool
pool_size = 0
pool_size += has_lowercase ? 26 : 0
pool_size += has_uppercase ? 26 : 0
pool_size += has_digits ? 10 : 0
pool_size += has_special ? 32 : 0
# Fórmula de Shannon
entropy = length(password) * log2(pool_size)
return entropy
end
La magia está en la función any() de Julia: itera sobre cada carácter y aplica un predicado. Código que se lee como inglés.
Building the Core: Código que importa
Generador de contraseñas
Nada de rand() básico. Usamos generación criptográficamente segura:
function generate_password(;
length::Int=16,
use_lowercase::Bool=true,
use_uppercase::Bool=true,
use_digits::Bool=true,
use_special::Bool=true
)::String
charset = Char[]
use_lowercase && append!(charset, LOWERCASE)
use_uppercase && append!(charset, UPPERCASE)
use_digits && append!(charset, DIGITS)
use_special && append!(charset, SPECIAL)
# Generación criptográficamente segura
password = String([rand(charset) for _ in 1:length])
return password
end
Derivación de claves (PBKDF2)
Tu contraseña maestra nunca se almacena. En su lugar, derivamos una clave de cifrado:
function derive_key(master_password::String, salt::Vector{UInt8}, iterations::Int=100_000)::Vector{UInt8}
key = Vector{UInt8}(master_password)
for _ in 1:iterations
key = sha256(vcat(key, salt))
end
return key
end
100,000 iteraciones hacen que los ataques de fuerza bruta sean extremadamente costosos. En producción, esto se reemplaza por Argon2id (el estándar actual recomendado por OWASP).
Cifrado simple (demo)
Para el demo, uso XOR + derivación de claves. NO USAR EN PRODUCCIÓN. Es educativo y funcional, pero para algo real necesitas AES-256-GCM:
function simple_encrypt(data::String, key::Vector{UInt8})::Vector{UInt8}
bytes = Vector{UInt8}(data)
encrypted = similar(bytes)
for i in eachindex(bytes)
encrypted[i] = bytes[i] ⊻ key[mod1(i, length(key))]
end
return encrypted
end
El operador ⊻ es XOR. Julia soporta símbolos Unicode matemáticos nativamente. Sí, puedes escribir ⊻ en lugar de xor(). Es gloriosa sobrecarga sintáctica.
Security Deep-Dive: ¿Qué falta para producción?
Este proyecto es una implementación educativa sólida, pero para uso real necesitas:
1. AES-256-GCM real
Usa Nettle.jl:
using Nettle
cipher = Cipher("AES256-GCM")
encrypt(cipher, key, iv, plaintext)
2. Argon2id en lugar de PBKDF2
Argon2 ganó la Password Hashing Competition y es resistente a ataques con hardware especializado (ASICs, GPUs):
using Argon2
key = argon2_hash(password, salt,
t_cost=3, # iteraciones
m_cost=12, # memoria (2^12 KB)
parallelism=1)
3. Protección contra timing attacks
Usa comparaciones de tiempo constante para verificar contraseñas:
function secure_compare(a::Vector{UInt8}, b::Vector{UInt8})::Bool
result = length(a) ⊻ length(b)
for (x, y) in zip(a, b)
result |= x ⊻ y
end
return result == 0
end
4. Limpieza de memoria
Sobrescribe secretos en memoria antes de liberar:
function wipe_memory!(data::Vector{UInt8})
fill!(data, 0x00)
GC.gc() # Forzar garbage collection
end
5. Protección del archivo vault
- Permisos de archivo restrictivos (
chmod 600) - Detección de modificaciones (HMAC)
- Backup cifrado automático
Por qué esto importa
El 80% de los hackeos exitosos involucran contraseñas débiles o reutilizadas. No es porque los sistemas sean inseguros, sino porque los humanos somos predecibles.
Este proyecto no es solo un gestor de contraseñas, es una herramienta educativa. Cada vez que generas o analizas una contraseña, ves en tiempo real:
- Cuántos bits de entropía tiene
- Cuánto tiempo tomaría romperla
- Por qué importa la longitud más que los símbolos
Ejemplo de salida real:
╔════════════════════════════════════════════╗
║ ANÁLISIS DE ENTROPÍA ║
╠════════════════════════════════════════════╣
║ Contraseña: ************
║ Longitud: 12 caracteres
║ Entropía: 78.49 bits
║ Fortaleza: 🟢 Fuerte
║ Tiempo de cracking estimado: 95.78 años
╚════════════════════════════════════════════╝
Ver esos números cambia cómo piensas sobre las contraseñas.
Lo que sigue
Este es solo el comienzo. Próximos features en mi roadmap:
- Integración con hardware tokens (YubiKey, Nitrokey)
- Autofill de navegador via extensión
- Sincronización cifrada (end-to-end, zero-knowledge)
- Auditoría de contraseñas contra bases de datos de leaks (Have I Been Pwned API)
- Generación de passphrases estilo XKCD (4-6 palabras aleatorias)
También estoy considerando portar esto a mi propio dialecto de Lisp con seguridad de memoria al estilo Rust (proyecto futuro que mencioné en mi post anterior sobre Common Lisp).
Úsalo, rómpelo, mejóralo
Repositorio: [Próximamente en GitHub - sígueme para el lanzamiento]
⚠️ DISCLAIMER: Este es un proyecto educativo. Para uso en producción, usa gestores establecidos como Bitwarden, 1Password, o KeePassXC. O al menos implementa las mejoras de seguridad que mencioné arriba.
Instalación rápida:
# Instalar Julia (si no lo tienes)
wget https://julialang-s3.julialang.org/bin/linux/x64/1.11/julia-1.11.2-linux-x86_64.tar.gz
tar -xvzf julia-1.11.2-linux-x86_64.tar.gz
# Dependencias necesarias
# SHA, Random, Dates, Base64 vienen con Julia base
# Solo necesitas instalar JSON3:
julia> using Pkg
julia> Pkg.add("JSON3")
# Guardar el código en password_manager.jl y ejecutar
julia password_manager.jl
Pruébalo:
# Generar contraseña
julia> generate_password(length=20)
"xK9#mL2$pQ7@vR4!nF8^"
# Analizar entropía
julia> analyze_password("Password123!")
# [salida mostrada arriba]
Dejen sus comentarios si:
- Han construido su propio gestor de contraseñas (cuéntenme qué stack usaron)
- Quieren ver la versión con AES-256-GCM real implementada
- Tienen ideas para mejorar el cálculo de entropía
- Solo vinieron por las ecuaciones matemáticas bonitas en código
- Piensan que Julia es overkill para esto (spoiler: tienen razón, pero no me importa)
No todo es sobre romper cosas.. cierto??
Serie: Construyendo herramientas de seguridad en lenguajes no convencionales
- Parte 1: Common Lisp Payload Generator
- Parte 2: C2 hecho con Nim
- Parte 3: Este post (Julia Password Manager)
This content originally appeared on DEV Community and was authored by rventz
rventz | Sciencx (2025-11-30T06:54:43+00:00) Construí un Gestor de Contraseñas Avanzado en Julia (oh si, Juliaaaa). Retrieved from https://www.scien.cx/2025/11/30/construi-un-gestor-de-contrasenas-avanzado-en-julia-oh-si-juliaaaa/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.