Core Tecnológico y R&D
White Papers & Investigación I+D
- 🧠 S.Y.N.A.P.T.I.C.A.: The Metacognitive Kernel (Tesis Doctoral).
- 🛰️ Artemis II: Caso de estudio sobre gestión de crisis y redundancia. (Draft)
- 🛡️ Ciberseguridad: Principios y análisis de criptografía aplicada, incluyendo Contraseñas de un solo uso (OTP).
Esta sección detalla mis habilidades técnicas y de ingeniería, fundamentales para el desarrollo de software, sistemas y la resolución de problemas tecnológicos.
Fundamentos de Programación
Tipos de lógica
Paradigmas de programación
Estructurado (estructuras base como búsquedas, árboles, etc…)
POO
Funcional (básico)
Algoritmos
Lenguajes de Programación
Para poder desarrollar todos los sistemas digitales se ha necesitado desarrollar lenguajes de programación.
Bases de Datos
| Base de Datos | Nivel |
|---|---|
| MySQL | :star::star::star::star::star: |
| MongoDB | :star::star::star::star::star: |
| MariaDB | :star::star::star::star: |
| SQL Server | :star::star::star::star: |
| SQLite | :star::star::star::star: |
| PostgreSQL | :star::star::star: |
| Oracle | :star::star: |
Estructuras de datos
Testing
Unit testing con Jest y PyTest
Integration testing
E2E testing con Cypress
Test-driven development (TDD)
Mocks y fakes
Documentación Técnica
- Markdown
- Diagrama con Mermaid
- UML básico
- Especificaciones funcionales y técnicas
Patrones de desarrollo
Clean Code
- Nombres significativos
- Funciones pequeñas
- Código autoexplicativo
- Separación de responsabilidades
Frameworks
- Frontend:
- HTML5, CSS3
- JavaScript / TypeScript
- Angular, React
- Backend:
- Node.js
- Express.js
- Frameworks adicionales:
- Django
- Flask
- Vue.js (básico)
Arquitecturas
- MVC
- Clean Architecture
- Monolitos vs Microservicios
- Serverless (introducción)
- Componentización avanzada
- Almacenamiento distribuido
Sistemas e infraestructuras
Esta área abarca el conjunto de componentes de hardware y software que sirven como base para construir, desplegar, ejecutar y escalar aplicaciones y servicios. Incluye desde la configuración de servidores y redes hasta la orquestación de contenedores y la automatización de la infraestructura.
DevOps
- CI/CD con GitHub Actions, Azure DevOps
- Docker
- Bash scripting
- Nginx básico
- Automatización de procesos con scripts
Ciberseguridad
La ciberseguridad es la práctica de proteger sistemas, redes y programas de ataques digitales. Abarca un conjunto de estrategias y tecnologías para garantizar la confidencialidad, integridad y disponibilidad de la información.
Para una exploración detallada de sus diferentes ramas y conceptos, consulta la sección de Ciberseguridad.
Automatizaciones
RPA
CI/CD
Especializaciones
Ciencia de Datos
| Herramienta | Nivel |
|---|---|
| Python | :star: |
| Jupyter Notebook | :star: |
| Keras | :star: |
| PyTorch | :star: |
| TensorFlow | :star::star: |
Modelos matemáticos
Blockchain
Redes neuronales
Machine learning
Inteligencia Artificial
Agentes Inteligentes
Computación Cuántica
Herramientas Transversales
Las herramientas más usadas en desarrollo de software se documentan en el apartado correspondiente.
⏫ Regresar al Centro de Conocimiento
Ciberseguridad
La ciberseguridad es el campo de la tecnología dedicado a proteger de ataques maliciosos los sistemas informáticos, las redes, los dispositivos y los datos. Abarca un amplio conjunto de estrategias, herramientas y marcos normativos.
Ramas de la Ciberseguridad
La ciberseguridad se puede dividir en varias disciplinas principales:
- Seguridad de Red: Protección de la infraestructura de red contra intrusiones, malware y accesos no autorizados.
- Seguridad de Aplicaciones (AppSec): Medidas para proteger el software y las aplicaciones contra vulnerabilidades durante el desarrollo y la producción.
- Seguridad en la Nube: Protección de los datos, aplicaciones e infraestructura alojados en la nube.
- Criptografía: Uso de algoritmos para cifrar y descifrar información, garantizando su confidencialidad e integridad.
- 🔍 Ejemplo de Criptoanálisis: Un ejemplo práctico de descifrado.
- Autenticación y Gestión de Identidad: Procesos para verificar la identidad de los usuarios y gestionar sus permisos.
- 🔑 Contraseñas de un solo uso (OTP): Mecanismos de autenticación que generan un código válido para una única sesión.
Ejemplo de Criptoanálisis

Problema inicial
En markdown
-
Se toma una tabla a partir de ejecutar un OCR.
C1 C2 C3 C4 C5 WIST\ FOZC\ AT_]U A]FGT XA_NT WSSOL O\ZE\ AX_IS ATE\T UN_N\ DBHUB SSIFO IAVHQ ]SRPA BLU_T BBIEB SN\EO ILV\C ]ORNO CLI_M BCVDZ BHIUD XU]QC EJWYS U_RRG ICENZ BTOU\ XSOQL EO\ES XIRRS YYGYB _MJSD UNHBJ MMHWQ FHKXG YTGE\ _UJN\ MNABL M\HLQ FAK\G MNFTM JUP]J JP[UB ZLU^Y QHAME MIFGM JNPOJ JR[AB ZNUCY QIAMA -
Se identifica la correspondencia entre filas por pares.
C1 C2 C3 C4 C5 WIST\ FOZC\ AT_]U A]FGT XA_NT WSSOL O\ZE\ AX_IS ATE\T UN_N\ ----- ----- ----- ----- ----- DBHUB SSIFO IAVHQ ]SRPA BLU_T BBIEB SN\EO ILV\C ]ORNO CLI_M ----- ----- ----- ----- ----- BCVDZ BHIUD XU]QC EJWYS U_RRG ICENZ BTOU\ XSOQL EO\ES XIRRS ----- ----- ----- ----- ----- YYGYB _MJSD UNHBJ MMHWQ FHKXG YTGE\ _UJN\ MNABL M\HLQ FAK\G ----- ----- ----- ----- ----- MNFTM JUP]J JP[UB ZLU^Y QHAME MIFGM JNPOJ JR[AB ZNUCY QIAMA -
Se retira todos los caracteres no textuales reemplazandolos por guion al piso.
C1 C2 C3 C4 C5 WIST_ FOZC_ AT__U A_FGT XA_NT WSSOL OZE AX_IS ATE_T UNN ----- ----- ----- ----- ----- DBHUB SSIFO IAVHQ _SRPA BLU_T BBIEB SN_EO ILV_C _ORNO CLI_M ----- ----- ----- ----- ----- BCVDZ BHIUD XU_QC EJWYS U_RRG ICENZ BTOU_ XSOQL EO_ES XIRRS ----- ----- ----- ----- ----- YYGYB _MJSD UNHBJ MMHWQ FHKXG YTGE_ UJN MNABL M_HLQ FAK_G ----- ----- ----- ----- ----- MNFTM JUP_J JP_UB ZLU_Y QHAME MIFGM JNPOJ JR_AB ZNUCY QIAMA -
Se consolida los guión bajo para que se iguale tanto la fila superior como la fila inferior en cada celda.
C1 C2 C3 C4 C5 WIST_ FZC AT__U A_F_T XAN WSSO_ OZE AX__S A_E_T UNN ----- ----- ----- ----- ----- DBHUB SS_FO IAV_Q _SRPA BLU_T BBIEB SN_EO ILV_C _ORNO CLI_M ----- ----- ----- ----- ----- BCVDZ BHIU_ XU_QC EJ_YS U_RRG ICENZ BTOU_ XS_QL EO_ES X_RRS ----- ----- ----- ----- ----- YYGY_ MJS UNHBJ M_HWQ FHK_G YTGE_ UJN MNABL M_HLQ FAK_G ----- ----- ----- ----- ----- MNFTM JUP_J JP_UB ZLU_Y QHAME MIFGM JNP_J JR_AB ZNU_Y QIAMA -
Se recorre cada caracter de la fila superior en cada celda y si el caracter no es igual en posición y en caracter con la fila inferior, se reemplaza por un guion al piso.
C1 C2 C3 C4 C5 W_S__ Z A____ A___T __N WSSO_ OZE AX__S A_E_T UNN ----- ----- ----- ----- ----- _B__B S___O I_V__ R _L___ BBIEB SN_EO ILV_C _ORNO CLI_M ----- ----- ----- ----- ----- _C__Z B_U X_Q E___S _RR ICENZ BTOU_ XS_QL EO_ES X_RRS ----- ----- ----- ----- ----- Y_G__ J N_B M_H_Q F_K_G YTGE_ UJN MNABL M_HLQ FAK_G ----- ----- ----- ----- ----- M_F_M J_P_J J___B Z_U_Y QAM MIFGM JNP_J JR_AB ZNU_Y QIAMA -
Vuelvo a consolidar guiones.
C1 C2 C3 C4 C5 W_S__ Z A____ A___T __N W_S__ Z A____ A___T __N ----- ----- ----- ----- ----- _B__B S___O I_V__ R _L___ _B__B S___O I_V__ R _L___ ----- ----- ----- ----- ----- _C__Z B_U X_Q E___S _RR _C__Z B_U X_Q E___S _RR ----- ----- ----- ----- ----- Y_G__ J N_B M_H_Q F_K_G Y_G__ J N_B M_H_Q F_K_G ----- ----- ----- ----- ----- M_F_M J_P_J J___B Z_U_Y QAM M_F_M J_P_J J___B Z_U_Y QAM -
Dado que no tiene significado al juntar la letras restantes, Regreso al punto 3 y ahora elimino los caracteres repetidos.
C1 C2 C3 C4 C5 I_T FOC _T__U _FG XA__T _S_OL O_E _X_IS _TE__ UN___ ----- ----- ----- ----- ----- DHU SIF _A_HQ _S_PA B_U_T BIE N_E _L__C _O_NO C_I_M ----- ----- ----- ----- ----- BCVD_ _HI_D _U__C JWY U___G ICEN_ _TO__ _SO_L O_E XI__S ----- ----- ----- ----- ----- _Y_YB _M_SD U_H_J M_W H_X T_E U_N M_A_L __L _A___ ----- ----- ----- ----- ----- N_T _U___ P_U _L___ _H__E I_G N_O R_A N_C _I__A -
Al concatenar la fila inferior de cada celda, encontramos el siguiente mensaje: “SOLO EXISTE UN BIEN, EL CONOCIMIENTO. SOLO EXISTE UN MAL, LA IGNORANCIA”.
En Hojas de cálculo
-
Se usa la misma tabla inicial.
C1 C2 C3 C4 C5 WIST\ FOZC\ AT_]U A]FGT XA_NT WSSOL O\ZE\ AX_IS ATE\T UN_N\ DBHUB SSIFO IAVHQ ]SRPA BLU_T BBIEB SN?EO ILV\C ]ORNO CLI_M BCVDZ BHIUD XU]QC EJWYS U_RRG ICENZ BTOU+ XSOQL EO\ES XIRRS YYGYB _MJSD UNHBJ MMHWQ FHKXG YTGE\ _UJN\ MNABL M?HLQ FAK\G MNFTM JUP]J JP[UB ZLU^Y QHAME MIFGM JNPOJ JR[AB ZNUCY QIAMA -
Luego se concatenan las filas con la siguiente formula:
=CONCATENAR(A1,B1,C1,D1,E1). -
Luego se concatenan las filas pares e impares resultantes con la siguiente formula:
=CONCATENAR(A12,A14,A16,A18,A20)y=CONCATENAR(A13,A15,A17,A19,A21) -
Se hacen los calculos necesarios para mostrar el mensaje:
=ARRAYFORMULA(TEXTJOIN("",VERDADERO,SI(EXTRAE(A23,FILA(INDIRECTO("1:"&LARGO(A23))),1)=EXTRAE(A24,FILA(INDIRECTO("1:"&LARGO(A24))),1),"_",EXTRAE(A24,FILA(INDIRECTO("1:"&LARGO(A24))),1)))) -
Se reunen todos los caracteres para darle un sentido al mensaje:
=REGEXREPLACE(A27,"[\_]","") -
Se separa cada palabra:
=REGEXREPLACE(A28,"[\\]"," ") -
Y se ponen los signos de puntuación:
=REGEXREPLACE(A29,"[\?]",", ")
Con Python
Se usa el siguiente código fuente:
Desencripción
import re
clave = "WIST\\FOZC\\AT_]UA]FGTXA_NTDBHUBSSIFOIAVHQ]SRPABLU_TBCVDZBHIUDXU]QCEJWYSU_RRGYYGYB_MJSDUNHBJMMHWQFHKXGMNFTMJUP\\JJP[UBZLU^YQHAME"
mensaje = "WSSOLO\\ZE\\AX_ISATE\\TUN_N\\BBIEBSN?EOILV\\C]ORNOCLI_MICENZBTOU?XSOQLEO\\ESXIRRSYTGE\\_UJN\\MNABLM?HLQFAK\\GMIFGMJNPOJJR[ABZNUCYQIAMA"
def vernam_decode(clave, mensaje):
mensaje_modificado_lista = list(mensaje) # Convertimos el mensaje a una lista para poder modificarlo
longitud_clave = len(clave)
longitud_mensaje = len(mensaje)
if longitud_mensaje != longitud_clave:
print("Las longitudes de clave y mensaje no son iguales: ", longitud_clave, ", ", longitud_mensaje)
return None
for i in range(longitud_clave):
if clave[i] == mensaje[i]:
mensaje_modificado_lista[i] = "_"
mensaje_modificado = "".join(mensaje_modificado_lista) # Volvemos a unir la lista en una cadena
mensaje_modificado = re.sub(r"[_?\\\\]", lambda m: "" if m.group(0) == "_" else "," if m.group(0) == "?" else " ", mensaje_modificado)
return mensaje_modificado
mensaje_modificado = vernam_decode(clave, mensaje)
if mensaje_modificado:
print("Clave:", clave)
print("Mensaje Original:", mensaje)
print("Mensaje Modificado:", mensaje_modificado)
Encripción
import random
import re
def generar_clave_dinamica(longitud):
"""Genera una clave aleatoria de la longitud especificada."""
caracteres = [chr(i) for i in range(32, 127)] # Caracteres ASCII imprimibles
return "".join(random.choice(caracteres) for _ in range(longitud))
def agregar_intrones(mensaje, num_intrones_por_caracter=1):
"""Agrega caracteres aleatorios (intrones) entre los caracteres del mensaje."""
mensaje_con_intrones = ""
caracteres = [chr(i) for i in range(32, 127)]
for char in mensaje:
mensaje_con_intrones += char
mensaje_con_intrones += "".join(random.choice(caracteres) for _ in range(num_intrones_por_caracter))
return mensaje_con_intrones
def eliminar_intrones(mensaje_con_intrones, num_intrones_por_caracter=1):
"""Elimina los intrones agregados, extrayendo el mensaje original."""
mensaje_original = ""
for i in range(0, len(mensaje_con_intrones), num_intrones_por_caracter + 1):
if i < len(mensaje_con_intrones):
mensaje_original += mensaje_con_intrones[i]
return mensaje_original
def vernam_encode_dinamico(mensaje_original, num_intrones=1):
"""
"Encripta" el mensaje original generando una clave dinámica de la misma longitud
y aplicando una lógica similar a la función vernam_encode anterior,
además de agregar intrones.
"""
clave = generar_clave_dinamica(len(mensaje_original))
mensaje_encriptado_lista = list(clave)
for i in range(len(mensaje_original)):
caracter_original = mensaje_original[i]
caracter_clave = clave[i]
if caracter_original == ",":
mensaje_encriptado_lista[i] = "?" if caracter_clave != "?" else random.choice([chr(j) for j in range(32, 127) if chr(j) != "?"])
elif caracter_original == " ":
mensaje_encriptado_lista[i] = "\\" if caracter_clave != "\\" else random.choice([chr(j) for j in range(32, 127) if chr(j) != "\\"])
elif caracter_original == "_":
mensaje_encriptado_lista[i] = caracter_clave
elif caracter_original == clave[i]:
mensaje_encriptado_lista[i] = random.choice([chr(j) for j in range(32, 127) if chr(j) != caracter_original])
else:
mensaje_encriptado_lista[i] = caracter_original
mensaje_encriptado_base = "".join(mensaje_encriptado_lista)
mensaje_encriptado_con_intrones = agregar_intrones(mensaje_encriptado_base, num_intrones)
return clave + "|||" + mensaje_encriptado_con_intrones # Incluimos la clave al inicio separada por "|||"
def vernam_decode_dinamico(mensaje_completo_encriptado, num_intrones=1):
"""
Decodifica el mensaje encriptado que incluye la clave y los intrones.
"""
partes = mensaje_completo_encriptado.split("|||")
if len(partes) != 2:
print("Formato de mensaje encriptado incorrecto.")
return None
clave = partes[0]
mensaje_con_intrones = partes[1]
mensaje_encriptado_base = eliminar_intrones(mensaje_con_intrones, num_intrones)
mensaje_modificado_lista = list(mensaje_encriptado_base)
if len(mensaje_encriptado_base) != len(clave):
print("Las longitudes de clave y mensaje encriptado no son iguales.")
return None
for i in range(len(clave)):
if clave[i] == mensaje_encriptado_base[i]:
mensaje_modificado_lista[i] = "_"
mensaje_modificado = "".join(mensaje_modificado_lista)
mensaje_desencriptado = re.sub(r"[_?\\\\]", lambda m: "" if m.group(0) == "_" else "," if m.group(0) == "?" else " ", mensaje_modificado)
return mensaje_desencriptado
# Ejemplo de uso dinámico:
mensaje_original_dinamico = "ESTE ES UN MENSAJE SECRETO CON ESPACIOS, COMAS Y _"
num_intrones_a_agregar = 2
mensaje_completo_encriptado = vernam_encode_dinamico(mensaje_original_dinamico, num_intrones_a_agregar)
if mensaje_completo_encriptado:
partes = mensaje_completo_encriptado.split("|||")
clave_generada = partes[0]
mensaje_con_intrones = partes[1]
print("Mensaje Original:", mensaje_original_dinamico)
print("Clave Generada:", clave_generada)
print("Mensaje Encriptado con Intrones:", mensaje_con_intrones)
mensaje_desencriptado_dinamico = vernam_decode_dinamico(mensaje_completo_encriptado, num_intrones_a_agregar)
if mensaje_desencriptado_dinamico:
print("Mensaje Desencriptado:", mensaje_desencriptado_dinamico)
print("Clave usada:", clave_generada)
Contraseñas de un solo uso (OTP)

Una Contraseña de un solo uso (OTP, por sus siglas en inglés One-Time Password) es una contraseña que es válida para una única sesión de inicio de sesión o transacción. Su gran ventaja es que, si un atacante la intercepta, no puede volver a utilizarla en el futuro, neutralizando los ataques de repetición (replay attacks).
Índice
- Contraseñas de un solo uso (OTP)
- Índice
- Tipos de Algoritmos OTP
- 🔬 Análisis Profundo: La Entropía en Semillas TOTP Cortas
- El Problema Oculto: El Desajuste de Bits (Base32 vs. Bytes)
- Demostración Práctica: La Colisión Masiva en Semillas de 2 Caracteres
- Cálculo Riguroso: Entropía Necesaria vs. Entropía Útil
- Conclusión y Recomendación para Desarrolladores
Tipos de Algoritmos OTP
Existen principalmente dos tipos de algoritmos para generar OTPs:
1. HOTP (HMAC-based One-Time Password)
Genera códigos basados en un contador que se incrementa con cada uso. Es como un ticket numerado: cada vez que pides uno, te dan el siguiente de la secuencia.
- Estándar: RFC 4226.
2. TOTP (Time-based One-Time Password)
Es el más común en la autenticación de dos factores (2FA). Genera códigos basados en el tiempo actual. El código cambia cada 30 o 60 segundos. Aplicaciones como Google Authenticator o Authy usan este método.
- Estándar: RFC 6238.
🔬 Análisis Profundo: La Entropía en Semillas TOTP Cortas
Objetivo: Determinar la longitud mínima efectiva de una semilla Base32 para cubrir el millón de posibles códigos OTP, demostrando cómo la arquitectura binaria induce colisiones masivas en semillas cortas.
El Problema Oculto: El Desajuste de Bits (Base32 vs. Bytes)
El algoritmo HMAC, que es el motor del TOTP, no trabaja directamente con texto, sino con bytes. Aquí surge un problema sutil pero crítico:
- Entrada (Semilla Base32): Cada carácter que escribimos aporta 5 bits de información.
- Procesador (HMAC): Trabaja sobre Bytes, que son grupos de 8 bits.
Imagina que tienes piezas de LEGO de 5 puntos y una base que solo acepta piezas de 8 puntos. Al intentar encajarlas, te sobrarán o faltarán puntos. En el mundo del software, los bits que sobran simplemente se descartan (truncan). Esta pérdida de información reduce drásticamente la seguridad real de la semilla.
Demostración Práctica: La Colisión Masiva en Semillas de 2 Caracteres
Una semilla de 2 caracteres (ej: AA) genera 10 bits ($2 \times 5$). El decodificador hace lo siguiente:
- Forma 1 Byte (8 bits): Usa los 5 bits del primer carácter y los 3 bits más importantes del segundo.
- Descarta el resto: Los 2 bits sobrantes del segundo carácter se tiran a la basura.
Consecuencia: El código OTP solo cambia cuando varían los 3 bits importantes del segundo carácter. Esto agrupa el alfabeto Base32 en 8 bloques de 4
caracteres. Por ejemplo, las semillas XA, XB, XC y XD ¡generarán el mismo OTP porque A, B, C y D comparten los mismos 3 bits superiores
(000xx)!
De las 1,024 combinaciones de 2 caracteres que podemos escribir, solo se generan 256 claves binarias únicas para el algoritmo.
Los “Disparadores de Cambio” (Change Triggers)
Un nuevo OTP solo se genera cuando el segundo carácter de la semilla es uno de los que inician un nuevo bloque de 4.
A (000xx), E (001xx), I (010xx), M (011xx), Q (100xx), U (101xx), Y (110xx), 4 (111xx).
Cálculo Riguroso: Entropía Necesaria vs. Entropía Útil
El objetivo es tener suficientes claves únicas para cubrir el millón de posibles OTPs de 6 dígitos. Para ello, necesitamos al menos 20 bits de entropía ($2^{20} \approx 1,048,576$).
Veamos cuántos “bits útiles” (los que no se descartan) obtenemos según la longitud de la semilla:
| Longitud (L) | Bits Totales ($L \times 5$) | Bytes Formados | Entropía Útil (Bits) | Total Claves Únicas ($2^{\text{Útiles}}$) | ¿Cubre $10^6$? |
|---|---|---|---|---|---|
| 2 | 10 bits | 1 Byte | 8 bits | 256 | ❌ |
| 3 | 15 bits | 1 Byte | 8 bits | 256 | ❌ |
| 4 | 20 bits | 2 Bytes | 16 bits | 65,536 | ❌ |
| 5 | 25 bits | 3 Bytes | 24 bits | $\mathbf{16,777,216}$ | ✅ |
| 6 | 30 bits | 3 Bytes | 24 bits | $16,777,216$ | ✅ |
| 7 | 35 bits | 4 Bytes | 32 bits | $4.29 \times 10^9$ | ✅ |
Conclusión y Recomendación para Desarrolladores
La tabla demuestra con certeza matemática que solo los bits que completan un byte son realmente utilizados por el algoritmo HMAC.
Para garantizar una generación de OTP robusta y evitar las colisiones por truncamiento, se necesita una clave binaria de al menos 3 bytes (24 bits).
Recomendación Técnica: La longitud mínima de una semilla TOTP debe ser de 5 caracteres Base32. Esto genera 24 bits efectivos, proveyendo más de 16 millones de claves únicas y cubriendo de sobra el espacio del millón de OTPs.
Utilizar semillas de 4 caracteres o menos debe considerarse una vulnerabilidad de implementación en cualquier entorno de producción.
Una Mirada al Futuro: Los Límites del Sistema
Es crucial entender que, aunque una semilla larga protege contra colisiones, no cambia la limitación fundamental del sistema: un OTP de 6 dígitos solo tiene un millón de combinaciones posibles. Este espacio de salida es el verdadero cuello de botella de la seguridad.
El Desafío Actual: Fuerza Bruta y Defensas Frágiles
Hoy, la principal defensa contra un ataque de fuerza bruta no es la complejidad del OTP, sino el bloqueo de intentos (rate limiting) impuesto por el servidor (ej. 3-5 intentos fallidos). Sin embargo, con el avance de la Inteligencia Actorial/IA, es plausible que se desarrollen técnicas de ataque que logren evadir o predecir estos mecanismos de defensa, reabriendo la puerta a la viabilidad de la fuerza bruta.
La Amenaza Cuántica: Rompiendo los Cimientos
La computación cuántica representa una amenaza aún más profunda, no para el espacio de $10^6$ directamente, sino para los algoritmos que lo sustentan:
- Algoritmo de Hash (SHA-1): El algoritmo de Grover podría reducir drásticamente el tiempo necesario para encontrar colisiones o invertir la función hash.
- Algoritmo Simétrico (HMAC): La seguridad de la clave simétrica también se ve debilitada por el algoritmo de Grover.
Soluciones y el Camino a Seguir
Para que la autenticación multifactor siga siendo segura, la industria debe enfocarse en dos áreas clave:
-
Aumentar la Longitud del OTP: Es la solución más inmediata y efectiva para ampliar el espacio de búsqueda y mitigar la fuerza bruta.
Longitud Espacio de Búsqueda ($10^N$) Incremento de Seguridad 6 dígitos $1,000,000$ (Base) 8 dígitos $100,000,000$ 100x más seguro 10 dígitos $10,000,000,000$ 10,000x más seguro -
Migración a Criptografía Post-Cuántica (PQC): A largo plazo, es imperativo reemplazar los algoritmos criptográficos actuales (como SHA-1 y HMAC) por estándares PQC que sean resistentes a los ataques de computadoras cuánticas.
En resumen, tu análisis es correcto: la clave secreta de alta entropía ya no es el principal desafío. La verdadera limitación es la probabilidad de acierto en el código de salida. Los sistemas futuros deben, obligatoriamente, aumentar la longitud del OTP y adoptar estándares criptográficos resistentes a la computación cuántica.
🔬 El Estado de la Investigación y Uso del OTP
La investigación no solo aborda las fallas de seguridad de OTP, sino también la fricción del usuario, que es un punto de dolor importante.
1. 🌐 Uso Actual de TOTP/OTP (Sí, es muy usado)
A pesar de sus limitaciones, el TOTP (y su forma más simple, OTP por SMS) sigue siendo la forma más común y aceptada de autenticación de segundo factor a nivel global.
- Aplicaciones Empresariales: Grandes empresas como Google, Microsoft y Amazon usan TOTP o notificaciones push como el estándar para la seguridad de cuentas.
- Fintech: Bancos y servicios de pago siguen usando OTP por SMS o correo electrónico para autorizar transacciones debido a su simplicidad y bajo costo.
- Motivo de su Dominio: La tecnología TOTP es un estándar abierto (RFC 6238), fácil de implementar en el servidor y muy barato de desplegar para el usuario.
2. 🧐 Investigación en Ciberseguridad sobre OTP
La comunidad de seguridad no ve a OTP como la solución final. La investigación se centra en dos áreas principales:
A. Ataques Exitosos y Fallas de Implementación La mayoría de los ataques exitosos no rompen el algoritmo TOTP en sí, sino la capa que lo rodea:
- Phishing de Sesión (MFA Fatigue): El atacante roba la contraseña y el código OTP en la misma sesión o satura al usuario con notificaciones push hasta que aprueba una por error.
- SIM Swapping (Ataques a OTP-SMS): El atacante toma control del número de teléfono del usuario, interceptando el SMS del OTP. Esto ha llevado a la recomendación de abandonar el OTP por SMS en favor de aplicaciones de autenticación.
B. Soluciones Post-OTP (FIDO2/WebAuthn) La investigación se ha volcado masivamente en estándares que eliminan la necesidad de que el usuario ingrese un código, como FIDO2 / WebAuthn. Este es el reemplazo directo y más prometedor de TOTP, utilizando criptografía de clave pública a través de hardware (Yubikeys) o biometría del dispositivo (FaceID, huella dactilar). Su gran ventaja es que detiene los ataques de phishing, ya que la clave criptográfica nunca sale del dispositivo.
3. 🧠 Investigación en la Intersección Biológica y Criptográfica
La investigación en biometría inmutable y cifrado de canal se encuentra en las áreas de Criptografía Aplicada y Biometría Fuzzy:
- Fuzzy Extractors y Fuzzy Vaults: Se investigan métodos matemáticos para convertir un dato biométrico inherentemente inexacto (como la lectura de un iris) en una clave criptográfica binaria perfecta y reproducible. Este es un campo activo pero aún lejos de la implementación masiva debido a la latencia y los desafíos de privacidad.
En resumen, OTP es la herramienta dominante actual, pero la investigación está enfocada en reemplazarlo con sistemas que manejan mejor la resistencia al phishing y que utilizan la clave pública (WebAuthn) o la biometría inmutable como factor de autenticación.
Más Allá del OTP: La Revolución de la Autenticación
La discusión sobre OTPs más largos y PQC es una evolución necesaria, pero el verdadero salto disruptivo en la gestión de identidad y acceso (IAM) reside en cambiar el factor de autenticación mismo y la forma en que aseguramos el canal de comunicación.
🧬 Biometría Inequívoca: El Factor “Quién Eres” Real
La biometría actual (huella, rostro) a menudo se puede copiar. El futuro apunta a datos biológicos únicos e inmutables que son extremadamente difíciles de falsear:
- ADN y Marcadores Genéticos: Aunque su uso es lento y plantea dilemas éticos, el ADN es el identificador más puro. En el futuro, se podrían usar marcadores genéticos específicos (como los SNPs) como una “clave” binaria única.
- Biometría Ocular Avanzada (Iris/Retina): Los patrones del iris y de los vasos sanguíneos de la retina son únicos incluso en gemelos idénticos, ofreciendo una seguridad muy superior.
- Autenticación Comportamental: Ya en uso, esta técnica crea un perfil continuo de cómo interactúas con tus dispositivos (velocidad al teclear, forma de sostener el teléfono, etc.). Si el comportamiento cambia, la autenticación falla.
🛡️ Criptografía de Canal Basada en Biología
Esta es la fusión de la biometría y la criptografía. En lugar de solo verificar la identidad, se usa la biología para cifrar la comunicación:
- Extracción de Clave (“Fuzzy Extractor”): Se extrae una clave binaria estable y de alta entropía a partir de datos biométricos “ruidosos” (que nunca son 100% idénticos en cada lectura).
- Cifrado de Sesión: Esa clave biológica se usa para derivar una clave efímera que cifra el canal de comunicación (similar al master secret en TLS).
El resultado es un canal cifrado con una clave que solo puede ser generada por la biología del individuo, moviéndonos de la Autenticación Multifactor (MFA) a una Autenticación Continua y Auto-Cifrante.
Conversación en LinkedIn
"Espero tus comentarios y reflexiones para seguir expandiendo este sistema..."
Discutir en LinkedInESTE NODO ESTÁ ABIERTO AL DIÁLOGO SOBERANO