Saltar al contenido principal

Algoritmos criptográficos

Passwork utiliza diferentes algoritmos criptográficos en el servidor y en el cliente.

Resumen de algoritmos

PropósitoAlgoritmoDónde se utiliza
Derivación de clave a partir de contraseñaPBKDF2Generación de clave maestra
Cifrado simétrico (servidor)AES-256-CFBCifrado de base de datos del lado del servidor
Cifrado simétrico (cliente)CryptoJS AES-256-CBCTodos los datos del cliente
Cifrado asimétricoRSA-OAEPIntercambio de claves
HashingSHA-256, SHA-512Verificación de contraseña, integridad
Generación de números aleatoriosWebCrypto APIGeneración de claves, IV, salt

PBKDF2 (Password-Based Key Derivation Function 2)

PBKDF2 se utiliza para derivar una clave criptográfica a partir de la contraseña maestra del usuario.

Parámetros del cliente

ParámetroValor
AlgoritmoPBKDF2
Función hashSHA-256
Iteraciones300.000
Longitud de clave de salida512 bits
Salt20 caracteres, único por usuario
Bibliotecapbkdf2 (npm)

Parámetros del servidor

ParámetroValor
AlgoritmoPBKDF2
Función hashSHA-512
Iteraciones600.000
Longitud de clave de salida512 bits
BibliotecaPHP hash_pbkdf2()
Diferencia de parámetros

SHA-256 con 300.000 iteraciones se utiliza en el cliente para lograr un equilibrio entre seguridad y rendimiento del navegador. Se aplican parámetros más estrictos (SHA-512, 600.000 iteraciones) en el servidor para el hashing de contraseñas de autenticación.

Salt

ParámetroValor
Longitud20 caracteres
AlfabetoA-Z, a-z, 0-9, @, ! (64 caracteres)
Entropía~120 bits
GeneraciónServidor, criptográficamente segura
AlmacenamientoServidor, en el perfil del usuario
UnicidadÚnico por usuario
Generación en el servidor

El salt siempre se genera en el servidor y se transmite al cliente. El cliente no genera el salt de forma independiente, lo que garantiza el uso de un generador criptográficamente seguro.

Formato del resultado

El resultado de PBKDF2 en el cliente se codifica como una cadena:

pbkdf:sha256:300000:64:{salt}

Propósito del alto número de iteraciones

Un alto número de iteraciones (300.000+) ralentiza significativamente los ataques de fuerza bruta:

  • Cada intento requiere un tiempo considerable
  • Se dificulta la fuerza bruta paralela con GPU
  • Las tablas precalculadas son imposibles debido al salt único

Migración automática de hashes

El sistema admite la migración automática de hashes PBKDF2 cuando cambian los parámetros.

Formato del hash del servidor:

pbkdf:{base64_hash}:{algorithm}:{iterations}:{length}:{salt}

Ejemplo: pbkdf:Abc123...==:sha512:600000:64:xY3zKmN9qR2w...

Mecanismo de migración:

  1. El usuario inicia sesión en el sistema
  2. El sistema verifica los parámetros del hash existente
  3. Si los parámetros difieren de la configuración actual → se requiere rehashing
  4. La contraseña se hashea automáticamente con los nuevos parámetros
  5. El nuevo hash se guarda en la base de datos

Lo que se puede actualizar:

ParámetroValor actualEjemplo de nuevos valores
Algoritmo de hashSHA-512SHA3-512, BLAKE2b512
Número de iteraciones600.0001.000.000, 2.000.000
Longitud de clave512 bits256, 1024 bits
Migración gradual

Cuando se actualizan los parámetros:

  • Nuevos usuarios → obtienen inmediatamente hashes con los nuevos parámetros
  • Usuarios existentes → la migración ocurre en el siguiente inicio de sesión
  • Usuarios sin inicio de sesión → los hashes antiguos siguen funcionando

La migración es transparente para los usuarios — simplemente introducen su contraseña como siempre.


AES (Advanced Encryption Standard)

Passwork utiliza diferentes modos AES en el servidor y en el cliente.

Cifrado del servidor: AES-256-CFB

AES-256 en modo CFB (Cipher Feedback) mediante OpenSSL se utiliza en el servidor.

ParámetroValor
AlgoritmoAES-256-CFB
Longitud de clave256 bits
Tamaño de bloque128 bits
Vector de inicialización (IV)128 bits, aleatorio por cifrado
BibliotecaOpenSSL (vía PHP)

Características del modo CFB:

  • Modo de cifrado de flujo
  • No requiere relleno
  • El IV se almacena con el texto cifrado

Uso: cifrado de datos en la base de datos (enlaces externos, configuración, contraseñas LDAP/SMTP).

Generación de IV del servidor:

ParámetroValor
Longitud128 bits
GeneradorCriptográficamente seguro (CSPRNG del SO)
UnicidadNuevo IV para cada operación de cifrado
AlmacenamientoAl inicio de los datos cifrados

Estructura de datos cifrados: [128 bit IV][ciphertext]

Cifrado del cliente: CryptoJS AES-256-CBC

La biblioteca CryptoJS se utiliza en el cliente para todas las operaciones de cifrado simétrico.

ParámetroValor
BibliotecaCryptoJS
ModoCBC (Cipher Block Chaining)
Longitud de clave256 bits
RellenoPKCS#7
IVAutomático (128 bits)
KDFFunción de derivación de clave integrada
Codificación de salidaBase32

Transformación de clave a AES-256:

Las claves simétricas en Passwork tienen 100 caracteres (~596 bits de entropía), pero AES-256 requiere exactamente una clave de 256 bits. CryptoJS realiza automáticamente la transformación mediante una función de derivación de clave (KDF):

  1. Se genera un salt aleatorio de 64 bits
  2. La clave original de 100 caracteres se transforma en una clave AES de 256 bits
  3. El salt se guarda con el texto cifrado para el descifrado
¿Por qué entropía redundante?

Los 596 bits de entrada garantizan la máxima fortaleza de la clave de salida de 256 bits. Esto también asegura la unificación — todas las claves simétricas (bóveda, registro, archivo adjunto) se generan de forma idéntica.

Generación de IV del cliente:

CryptoJS genera automáticamente el IV para cada cifrado:

ParámetroValor
Longitud128 bits
Generadorwindow.crypto.getRandomValues()
UnicidadNuevo IV para cada operación de cifrado
Formato de almacenamientoIncluido en formato compatible con OpenSSL

Formato de salida de CryptoJS: "Salted__" + [64 bit salt] + [ciphertext with IV] → Base64

¿Por qué diferentes modos?

CriterioServidor (CFB)Cliente (CBC)
BibliotecaOpenSSLCryptoJS
Razón de elecciónEstándar de PHPCompatibilidad retroactiva
VentajasModo de flujoAmplio soporte

CryptoJS vs WebCrypto API

La biblioteca CryptoJS se utiliza para el cifrado simétrico en el cliente, no la API nativa WebCrypto. A continuación se presenta una comparación.

Comparación:

AspectoCryptoJSWebCrypto API
ImplementaciónJavaScript puroCódigo nativo del navegador
RendimientoMás lentoSignificativamente más rápido
Protección contra ataques de temporizaciónSin garantíasProtección a nivel de implementación
Gestión de memoriaClaves en el heap de JSLas claves pueden ser no extraíbles
APISíncronaAsíncrona (Promise)
CompatibilidadCualquier entorno JSSolo navegadores modernos

Por qué se utiliza CryptoJS:

  1. Compatibilidad retroactiva — los datos cifrados existentes utilizan el formato CryptoJS
  2. API síncrona — integración más sencilla con la base de código existente
  3. Universalidad — funciona en cualquier entorno JavaScript

Medidas de seguridad en la implementación actual:

  • PBKDF2 mediante biblioteca separada — la clave maestra se deriva mediante PBKDF2 criptográficamente robusto
  • WebCrypto para RSA — las operaciones asimétricas críticas se realizan mediante la API nativa
  • Generación de IV criptográficamente segura — mediante crypto.getRandomValues(), no Math.random()
  • Los datos se cifran una vez — los ataques de temporización requieren múltiples operaciones con la misma clave

Evaluación de riesgos:

AmenazaNivel de riesgoJustificación
Ataques de temporizaciónBajoRequiere acceso local al navegador
Exposición de memoriaBajoCon dicho acceso, es más fácil interceptar la contraseña durante la entrada
CVE conocidosMínimoLa versión de CryptoJS utilizada no tiene vulnerabilidades críticas
Desarrollo futuro

Las versiones futuras planifican una transición gradual a la API WebCrypto para el cifrado simétrico. Esto permitirá:

  • Usar AES-GCM (cifrado autenticado) en lugar de AES-CBC
  • Mejora del rendimiento de 10-100x
  • Protección de claves a nivel del navegador

La migración se realizará con compatibilidad retroactiva para los datos existentes.


RSA (Rivest–Shamir–Adleman)

RSA se utiliza para el cifrado asimétrico — intercambio seguro de claves simétricas entre usuarios.

Parámetros

ParámetroValor
AlgoritmoRSA-OAEP
Longitud del módulo2048 bits
Exponente público65537 (0x010001)
Función hashSHA-256
BibliotecaWebCrypto API (crypto.subtle)

Generación de claves

Las claves RSA se generan en el cliente mediante la API WebCrypto:

crypto.subtle.generateKey({
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: 'SHA-256'
}, true, ['encrypt', 'decrypt'])

Formatos de almacenamiento

ClaveFormatoDescripción
PúblicaSPKI (PEM)SubjectPublicKeyInfo
PrivadaPKCS#8 (PEM)Cifrada con clave maestra

Formatos compatibles

El sistema admite la importación de claves en formatos:

  • PKCS#1-----BEGIN RSA PRIVATE KEY-----
  • PKCS#8-----BEGIN PRIVATE KEY-----
  • SPKI-----BEGIN PUBLIC KEY-----
  • JWK — JSON Web Key (para conversión)

Compatibilidad retroactiva

Para claves heredadas de 1024 bits, se utiliza la biblioteca JSEncrypt como alternativa, ya que la API WebCrypto no admite RSA-1024.

¿Por qué RSA-2048?

AspectoDescripción
SeguridadEquivalente a 112 bits de cifrado simétrico
RendimientoVelocidad aceptable en el navegador
CompatibilidadAmplio soporte en todos los navegadores

Hashing

SHA-256

ParámetroValor
Longitud del hash256 bits
Biblioteca (cliente)js-sha256
UsoHash de clave maestra, PBKDF2, RSA-OAEP

SHA-512

ParámetroValor
Longitud del hash512 bits
Biblioteca (cliente)js-sha512
Biblioteca (servidor)PHP hash()
UsoPBKDF2 del servidor, hash de clave del servidor, índices de búsqueda

Generación de números aleatorios

Todos los parámetros criptográficos se generan utilizando generadores de números aleatorios criptográficamente seguros (CSPRNG).

Fuentes de entropía

Servidor (PHP)

GeneradorFuente de entropíaUso
random_bytes()CSPRNG del SODatos binarios (claves, tokens)
random_int()CSPRNG del SOCadenas de caracteres (salts, códigos)

Fuentes de entropía del SO:

  • Linux: /dev/urandom, llamada al sistema getrandom()
  • Windows: CryptGenRandom() (CryptoAPI)
  • macOS: arc4random_buf()

Cliente (JavaScript)

GeneradorFuente de entropíaUso
window.crypto.getRandomValues()CSPRNG del navegador/SONúmeros, arrays
CryptoJS.lib.WordArray.random()crypto.getRandomValues()IV para AES

Fuentes de entropía del navegador:

  • Chromium/Electron: BoringSSL CSPRNG
  • Firefox: NSS (Network Security Services)
  • Safari: CommonCrypto (Apple)

Garantías de fortaleza criptográfica

PropiedadGarantía
ImprevisibilidadImposible predecir el siguiente valor
Distribución uniformeTodos los valores son igualmente probables
Sin sesgoSe utiliza muestreo por rechazo
DisponibilidadLos generadores no se bloquean

Claves y tokens generados

Qué se generaLongitudAlfabetoEntropía
Claves simétricas
Clave de bóveda100 caracteresA-Z, a-z, 0-9, @, !~596 bits
Clave de registro100 caracteresA-Z, a-z, 0-9, @, !~596 bits
Clave de archivo adjunto100 caracteresA-Z, a-z, 0-9, @, !~596 bits
Clave de enlace100 caracteres → 256 bitsA-Z, a-z, 0-9, @, !~596 bits entrada
Clave de cifrado del servidor256 bitsBinario256 bits
Salts
Salt PBKDF220 caracteresA-Z, a-z, 0-9, @, !~120 bits
Salt de bóveda32 caracteresA-Z, a-z, 0-9, @, !~190 bits
Tokens y secretos
Secret Code (localStorage)100 caracteresA-Z, a-z, 0-9~596 bits
Extension Secret60 caracteresA-Z, a-z, 0-9~357 bits
Auth Token (extensión)400 bitsHex400 bits
Token de enlace externo43 caracteresA-Z, a-z, 0-9~256 bits
Tokens de sesión
Access Token256 bitsBase64256 bits
Refresh Token256 bitsBase64256 bits
Vectores de inicialización
IV (servidor, AES-CFB)128 bitsBinario128 bits
IV (cliente, AES-CBC)128 bitsBinario128 bits

Verificación de unicidad de tokens

Para los tokens que requieren unicidad garantizada (tokens de enlace, códigos de invitación), se realiza una verificación en la base de datos:

  1. Se genera un token aleatorio
  2. Se verifica la unicidad en la base de datos
  3. En caso de colisión — se regenera
  4. Se devuelve un token garantizado como único

Probabilidad de colisión:

  • 43 caracteres de 62: ~10^77 combinaciones
  • Con mil millones de tokens: probabilidad de colisión ≈ 10^-59
  • Prácticamente imposible

Bibliotecas criptográficas

Cliente (JavaScript/TypeScript)

BibliotecaPropósito
WebCrypto APIOperaciones RSA, números aleatorios
CryptoJSCifrado AES (todos los datos)
js-sha256Hashing SHA-256
js-sha512Hashing SHA-512
pbkdf2Derivación de clave PBKDF2
node-jsencryptAlternativa RSA (1024 bits)
pem-jwkConversión PEM ↔ JWK
totp-generatorGeneración de códigos TOTP

Servidor (PHP)

ComponentePropósito
OpenSSLCifrado AES-256-CFB
hash()Hashing SHA-256, SHA-512
hash_pbkdf2()Derivación de clave PBKDF2
random_bytes()Generación de datos aleatorios

Comparación con estándares de la industria

ParámetroPassworkRecomendaciones NIST (2024)Estado
Cifrado simétricoAES-256AES-128/192/256
Cifrado asimétricoRSA-2048RSA-2048+
HashingSHA-256/512Familia SHA-2
Iteraciones PBKDF2300K/600K≥310K (SHA-256)
Generador de números aleatoriosCSPRNGCSPRNG