Arquitectura Criptográfica de FoxNotes

La seguridad en el desarrollo de software no es un estado que se alcanza y se olvida; es un proceso continuo y una responsabilidad enorme. Cuando comencé a desarrollar FoxNotes, mi premisa fundamental fue la soberanía absoluta de los datos. Esto significa que tú, como usuario, eres el único custodio verdadero de tu información.

Para garantizar esta promesa, decidĂ­ que la aplicaciĂłn no debĂ­a confiar en la seguridad del sistema operativo que uses, ni tampoco en la seguridad de la nube donde decidas sincronizar tus archivos. La seguridad debe residir en el archivo mismo y en la memoria RAM de tu computadora durante su ejecuciĂłn.

Este documento detalla exhaustivamente los algoritmos, las estructuras de datos y las decisiones de diseño arquitectónico que he programado en el motor criptográfico de FoxNotes, utilizando C# (.NET 9 MAUI). Vamos a analizar paso a paso desde cómo protejo tu contraseña en la memoria volátil hasta el cifrado doble (en cascada) que utilizo para proteger cada letra de tu texto plano.

1. La Primera Línea de Defensa: Protección de tu Contraseña en la Memoria Volátil (RAM)

El eslabón más débil en cualquier sistema criptográfico casi siempre suele ser cómo la aplicación maneja la contraseña maestra que el usuario escribe. En lenguajes de programación como C# (el ecosistema de .NET), los tipos de datos básicos que usamos para el texto, como el string, presentan un riesgo de seguridad crítico: son inmutables y son administrados por algo llamado el Recolector de Basura (Garbage Collector o GC).

Imagina la memoria RAM como una gran pizarra y al Recolector de Basura como el conserje. Cuando escribes tu contraseña y esta se almacena en un string normal, es como escribir en la pizarra con un marcador permanente. Tú no puedes borrarla a voluntad. Si el valor de la variable cambia, .NET simplemente crea un nuevo string en otra parte de la pizarra y deja el anterior ahí tirado, huérfano, hasta que el conserje (el GC) decida que es hora de limpiar.

Esto significa que un volcado de memoria (memory dump), un ataque de arranque en frío (donde congelan tu memoria RAM para extraer datos) o un virus con acceso a la memoria de la aplicación podría extraer tu contraseña en texto plano mucho tiempo después de que hayas dejado de usar FoxNotes.

Para mitigar este gravĂ­simo vector de ataque, he programado una clase especial llamada SecurePasswordHolder.

La ImplementaciĂłn del SecurePasswordHolder

Esta clase actĂşa como un contenedor de alta seguridad utilizando System.Security.SecureString. Un SecureString no escribe con marcador permanente; cifra su contenido directamente en la memoria RAM utilizando las herramientas de protecciĂłn de datos de tu propio sistema operativo (como DPAPI en Windows). Además, obligo a que se almacene en “memoria no administrada” (unmanaged memory). En nuestra analogĂ­a, esto es sacar la contraseña de la pizarra del conserje y meterla en una caja fuerte personal donde el Recolector de Basura de .NET no puede moverla ni hacerle copias accidentales.

Veamos exactamente cómo implementé la extracción segura en el código:

C#

public byte[]? GetPasswordBytes()
{
    if (_securePassword == null || _securePassword.Length == 0)
        return null;
    
    // 1. AsignaciĂłn en memoria no administrada: Pido la llave de la caja fuerte
    IntPtr ptr = Marshal.SecureStringToGlobalAllocUnicode(_securePassword);
    try
    {
        int length = _securePassword.Length;
        char[] chars = new char[length];
        
        // 2. Copia temporal a un arreglo de caracteres (solo por un instante)
        Marshal.Copy(ptr, chars, 0, length);
        
        // 3. Conversión a bytes UTF-8 para que las funciones matemáticas lo entiendan
        byte[] utf8Bytes = Encoding.UTF8.GetBytes(chars);
        
        // 4. EL PASO CRĂŤTICO: Saneamiento inmediato del arreglo temporal
        Array.Clear(chars, 0, chars.Length);
        
        return utf8Bytes;
    }
    finally
    {
        // 5. Destrucción criptográfica de la memoria no administrada
        Marshal.ZeroFreeGlobalAllocUnicode(ptr);
    }
}

Análisis del Flujo de Memoria

El método GetPasswordBytes() que ves arriba es mi aproximación en cuanto a la paranoia de la memoria. Funciona así:

  1. Transforma el SecureString que estaba cifrado en un puntero (IntPtr), que no es más que una dirección hacia un bloque de memoria no administrada.
  2. Copia los caracteres a un arreglo temporal char[] administrado, pero solo durante el instante estrictamente necesario para convertirlo al formato de bytes (UTF-8).
  3. El Punto Crítico: Inmediatamente después de obtener los bytes, utilizo Array.Clear para sobrescribir ese arreglo temporal de caracteres con ceros.
  4. En el bloque finally (que es una regla de programación que asegura que este código se ejecutará siempre, incluso si la computadora lanza un error o una excepción catastrófica), utilizo Marshal.ZeroFreeGlobalAllocUnicode(ptr). Esta es una función nativa profunda que no solo libera la memoria no administrada, sino que le escribe ceros encima antes de devolverle el espacio al sistema operativo.

¿Cuál es el resultado de todo esto? Tu contraseña en texto plano, la que escribiste con el teclado, existe en la memoria RAM durante apenas unos pocos milisegundos. Después es destruida de forma proactiva, reduciendo drásticamente la ventana de oportunidad para cualquier atacante que intente espiar el cerebro de tu computadora.

2. DerivaciĂłn de Claves (KDF): Mi Motor Dual y la Resistencia a Hardware Especializado

Una contraseña humana (por muy compleja que sea, tipo Micontraseña123!) rara vez tiene la entropía, es decir, la aleatoriedad matemática necesaria para ser utilizada directamente como una llave de cifrado de 256 bits (que son 32 bytes de puro caos matemático). Para transformar tu contraseña humana en claves criptográficas invulnerables, utilizamos herramientas llamadas Funciones de Derivación de Clave (KDF: Key Derivation Functions).

La enorme mayoría de las aplicaciones comerciales de notas utilizan un solo algoritmo para esto (generalmente uno llamado PBKDF2 o bcrypt). En FoxNotes, sin embargo, decidí elevar el estándar implementando un sistema de derivación dual. Este sistema combina simultáneamente dos de los algoritmos más robustos que existen en la criptografía moderna: PBKDF2-SHA512 y Argon2id.

El Problema de la Fuerza Bruta y las Gráficas (ASICs)

Hoy en día, los atacantes modernos no intentan adivinar tu contraseña sentándose a teclear palabras. Utilizan tarjetas gráficas de videojuegos de altísima gama (GPUs) o incluso fabrican chips de hardware a medida (ASICs) diseñados exclusivamente para calcular combinaciones a velocidades ridículas de miles de millones de intentos por segundo.

Para combatir a estos monstruos de silicio, una funciĂłn derivadora (KDF) debe ser sumamente “costosa” de calcular para la máquina. Este costo se lo podemos cobrar al atacante de dos formas: en tiempo de procesador (CPU) o exigiĂ©ndole muchĂ­sima memoria RAM. Yo decidĂ­ cobrarle ambas.

PBKDF2-SHA512 (Cobrando el costo en Procesador / CPU)

El primer motor de FoxNotes utiliza Password-Based Key Derivation Function 2 (PBKDF2), apoyándose en SHA-512 como su algoritmo matemático base. En las opciones de FoxNotes, te permito configurar la cantidad de iteraciones (vueltas) que quieres darle a tu clave, pero he impuesto desde el código un límite mínimo estricto de 100,000 iteraciones (MIN_ITERATIONS). Esto significa que, por cada único intento de adivinar tu contraseña, el procesador del atacante debe aplicar el complejo algoritmo SHA-512 como mínimo cien mil veces consecutivas sobre sí mismo. Esto hace que los ataques de diccionario (probar palabras comunes) o de fuerza bruta se vuelvan exponencialmente dolorosos y lentos.

Argon2id (Cobrando el costo en Memoria RAM)

Aunque cobrar en tiempo de procesador con PBKDF2 es excelente, las corporaciones maliciosas o atacantes con mucho presupuesto pueden fabricar chips ASICs que calculen ese SHA-512 de forma increíblemente eficiente, saltándose mi barrera.

AquĂ­ es donde entra a jugar la segunda carta de triunfo: Argon2id, el ganador de la prestigiosa competencia mundial Password Hashing Competition. Argon2id es un algoritmo “resistente a la memoria” (memory-hard). En el Servicio de CriptografĂ­a de FoxNotes (CryptoService.cs), lo he configurado de manera inamovible con los siguientes parámetros auditados:

  • ARGON2_MEMORY = 60416: Exige aproximadamente 60 Megabytes de RAM por cada cálculo.
  • ARGON2_ITERATIONS = 4: El algoritmo tiene que recorrer y mezclar toda esa memoria 4 veces.
  • ARGON2_PARALLELISM = 1: Se asegura de utilizar un solo hilo de procesamiento para no saltarse pasos.

Esta configuración es una pesadilla para un hacker. Obliga a cualquier atacante que intente crackear la contraseña a tener al menos 60 Megabytes de RAM disponibles por cada intento simultáneo. Si un clúster de tarjetas gráficas intenta probar 10,000 contraseñas por segundo, necesitaría 600 Gigabytes de RAM ultrarrápida exclusiva para eso, lo cual destruye completamente la viabilidad económica y técnica del ataque.

La FusiĂłn: CreaciĂłn de tu Clave Maestra mediante XOR

Lo que hace que la arquitectura de FoxNotes sea excepcionalmente resistente es cómo se combinan estos dos algoritmos. En lugar de darte a elegir uno, la aplicación calcula ambos y luego los fusiona mediante una operación matemática a nivel de bits llamada XOR (^).

C#

byte[] hashA = PBKDF2_SHA512(passwordBytes, salt, iterationsSha512, HASH_SIZE);
byte[] hashB = Argon2idDerive(passwordBytes, salt, HASH_SIZE);

masterKey = new byte[HASH_SIZE]; // HASH_SIZE es 64 bytes
for (int i = 0; i < HASH_SIZE; i++)
    masterKey[i] = (byte)(hashA[i] ^ hashB[i]); // La gran fusiĂłn

ÂżPor quĂ© uso XOR? La operaciĂłn XOR (O exclusivo) tiene una propiedad matemática fascinante y casi mágica: si fusionas dos cadenas de bytes, y al menos una de ellas es criptográficamente perfecta y segura, el resultado final será completamente seguro, sin importar lo mala que fuera la otra. Esto es un seguro a futuro. Si el dĂ­a de mañana se descubre una vulnerabilidad matemática catastrĂłfica en Argon2id que permita romperlo en segundos, la clave maestra de tus notas en FoxNotes seguirá protegida por la fuerza inmensa de PBKDF2, y viceversa. Es un diseño de “Defensa en Profundidad”, pensado deliberadamente para resistir el paso del tiempo y los inevitables avances criptoanalĂ­ticos de las prĂłximas dĂ©cadas.

De esta clave maestra enorme de 64 bytes (masterKey), FoxNotes la divide en dos mitades exactas:

  • key1 (32 bytes): Destinada a alimentar el motor de cifrado interno (ChaCha20).
  • key2 (32 bytes): Destinada a alimentar el motor de cifrado externo (AES-GCM).

3. El Cifrado HĂ­brido en Cascada: ChaCha20 + AES-256-GCM

Una vez que el sistema ha derivado de forma segura las claves key1 y key2 a partir de tu contraseña, FoxNotes procede a cifrar el texto plano de la nota que acabas de escribir. En lugar de depender de un solo candado (un solo algoritmo de cifrado), utilizo una técnica conocida como Cifrado en Cascada (Cascade Encryption).

Imagina que metes tu diario en una caja fuerte y luego agarras esa caja fuerte entera y la metes dentro de una bóveda más grande con un candado de otra marca. Esto significa que los datos se cifran primero con un algoritmo, y el resultado de eso se vuelve a cifrar con un algoritmo completamente diferente.

La Capa Interna: ChaCha20 (El Cifrado de Flujo)

La primera capa de este blindaje se realiza utilizando ChaCha20. Desarrollado por el renombrado criptĂłgrafo Daniel J. Bernstein, ChaCha20 es lo que se conoce como un cifrado de flujo (stream cipher).

A diferencia de los cifrados tradicionales (que agarran tu texto y lo dividen en bloquecitos fijos), un cifrado de flujo funciona como una manguera a presión. Genera un flujo pseudoaleatorio infinito de bits (ruido matemático) basado en la key1 y en un nonce (un número especial de 12 bytes que se usa una sola vez en toda la historia para esa nota). Luego, este chorro de ruido se combina con tus palabras.

C#

private static byte[] ChaCha20Encrypt(byte[] plain, byte[] key, byte[] nonce)
{
    var cipher = new ChaCha7539Engine();
    cipher.Init(true, new ParametersWithIV(new KeyParameter(key), nonce));
    byte[] ciphertext = new byte[plain.Length];
    cipher.ProcessBytes(plain, 0, plain.Length, ciphertext, 0);
    return ciphertext;
}

ElegĂ­ usar ChaCha20 aquĂ­ porque sus ventajas son enormes:

  1. Inmunidad a ataques de caché/tiempo (Timing Attacks): Como ChaCha20 hace operaciones matemáticas puras que no dependen de ir a buscar cosas a la memoria (las famosas tablas S-boxes), el tiempo que tarda tu procesador en ejecutarlo es siempre exactamente el mismo. Un atacante no puede espiar cuántos milisegundos tarda tu CPU en cifrar para intentar adivinar la clave.
  2. Difusión extrema: Me aseguro de que el texto original que escribiste se convierta en ruido blanco criptográfico perfecto antes de siquiera pasarlo a la segunda etapa.

La Capa Externa: AES-256-GCM (Cifrado Autenticado)

Una vez que tus datos han sido cifrados y convertidos en ruido por ChaCha20, tomo esa matriz de bytes resultante (cipher1) y la paso a la segunda caja fuerte: el estándar mundial de la industria, AES (Advanced Encryption Standard), usando la máxima longitud de claves de 256 bits y operando en un modo especial llamado GCM (Galois/Counter Mode).

El modo GCM es crítico para mi filosofía de protección. Verás, AES por sí solo oculta los datos, pero no garantiza que nadie los modifique en secreto mientras están guardados en tu disco duro. Si un atacante (o un disco duro dañado) alterara un solo byte del texto cifrado, un algoritmo AES normal simplemente te descifraría basura sin avisar, y la aplicación podría cerrarse inesperadamente, arruinando tu nota.

GCM convierte a AES en algo superior: un sistema AEAD (Authenticated Encryption with Associated Data). Mientras la bĂłveda AES cifra los datos, el motor GCM realiza cálculos matemáticos sĂşper avanzados sobre algo llamado “Campo de Galois” (Galois Field). El objetivo de esto es generar un Sello de AutenticaciĂłn (Authentication Tag) de 16 bytes. Funciona como un sello de cera en una carta antigua.

C#

private static byte[] AesGcmEncrypt(byte[] plain, byte[] key, byte[] nonce, byte[]? associatedData = null)
{
    using var aes = new AesGcm(key, 16); // Preparo el espacio de 16 bytes para el Sello
    byte[] ciphertext = new byte[plain.Length];
    byte[] tag = new byte[16];

    if (associatedData != null)
        aes.Encrypt(nonce, plain, ciphertext, tag, associatedData); // Cifrado con reglas pĂşblicas
    else
        aes.Encrypt(nonce, plain, ciphertext, tag);

    // Pego el texto cifrado y el Sello de AutenticaciĂłn juntos para guardarlos
    byte[] result = new byte[ciphertext.Length + tag.Length];
    Buffer.BlockCopy(ciphertext, 0, result, 0, ciphertext.Length);
    Buffer.BlockCopy(tag, 0, result, ciphertext.Length, tag.Length);
    return result;
}

Durante el proceso inverso (cuando pones tu clave para abrir la nota), mi método AesGcmDecrypt primero se detiene y verifica matemáticamente este Sello. Si un solo bit del archivo .fox ha sido alterado, ya sea por un archivo corrupto o por la mano de un hacker, la verificación del Sello fallará y el sistema lanzará inmediatamente una excepción AuthenticationTagMismatchException. Esto bloquea el acceso en seco antes de siquiera intentar procesar los datos corruptos. Esto garantiza la Integridad total de tus notas además de su Confidencialidad.

Al poner ChaCha20 dentro de AES-256-GCM, aseguro que un atacante tendría que romper no uno, sino dos algoritmos criptográficos fundamentalmente distintos y sin fallas conocidas para poder leer una sola palabra de lo que escribiste.

4. Datos Autenticados Asociados (AAD): El Pegamento Matemático

Existe un ataque avanzado contra los sistemas cifrados llamado “intercambio de metadatos” (Metadata Swapping). Todo archivo cifrado en el mundo necesita almacenar una pequeña parte de informaciĂłn pĂşblica, en texto plano, justo al inicio del archivo. Esta informaciĂłn incluye cosas vitales como el Vector de InicializaciĂłn (el nĂşmero aleatorio o Nonce), la Sal (Salt) y el nĂşmero de iteraciones que elegiste en las opciones.

Si dejo esta información pública sin protección, un atacante astuto podría hacer trampa: agarrar el encabezado de un archivo .fox tuyo muy antiguo (cuando quizás usabas menos iteraciones) y pegarlo en tu archivo nuevo. Esto forzaría a FoxNotes a utilizar parámetros débiles para abrir tu nota, lo que podría debilitar el escudo o causar que la app se vuelva loca.

Para prevenir esto de forma elegante, diseñé el código para inyectar estos metadatos dentro de la matemática del Sello de AES-GCM usando una función llamada AAD (Additional Authenticated Data).

C#

// 1. Tomo tus reglas pĂşblicas y las convierto a un formato legible (Base64)
string saltBase64 = Convert.ToBase64String(salt);
string nonceBase64 = Convert.ToBase64String(nonce);

// PUNTO CLAVE: Meto esas reglas en una variable AAD
aad = Encoding.UTF8.GetBytes($"{TEXT_MAGIC}::{saltBase64}::{nonceBase64}::{iterationsSha512}");

// Cifro la nota y le digo a AES-GCM que genere el Sello VINCULADO a estas reglas
cipher2WithTag = AesGcmEncrypt(cipher1, key2, nonce, aad);

Cuando AES-GCM calcula ese famoso Sello de cera de 16 bytes, incluye todo el contenido de la variable aad en su ecuación matemática, aunque esos datos en sí no se cifren (porque deben ser legibles).

¿Cuál es el resultado de esta maniobra? Que tu texto cifrado queda matemáticamente amarrado (bound) a sus metadatos específicos. Si un virus o un curioso abre tu nota en un bloc de notas e intenta modificar el campo de iterationsSha512 de 200,000 a un más veloz 100,000, al momento de intentar abrirla en FoxNotes, el sistema inyectará esa regla alterada en la fórmula matemática. Inmediatamente, el cálculo del Sello dará un resultado distinto al Sello original guardado, y la aplicación te arrojará un error de integridad bloqueando el archivo. Ninguna regla de tu archivo puede ser manipulada sin invalidar todo el contenido por completo.

5. Tratamiento de Archivos Adjuntos (Imágenes): Equilibrio Perfecto entre Seguridad y Velocidad

Una de las características de las que más me enorgullezco (Y que costó más debuggear 🫠) en FoxNotes es que los archivos .fox son ecosistemas autocontenidos. Si pegas una imagen dentro de tu nota, yo no guardo esa foto como un archivo .png en una carpeta oculta de tu Windows. Lo que hace FoxNotes es agarrar esa imagen entera, convertirla en un larguísimo bloque de texto (Base64), cifrarlo y meterlo en el vientre del archivo de tu nota. Si copias tu .fox a una llave maya, te llevas tu texto y tus fotos, todo protegido.

Sin embargo, aquí me enfrenté a un reto como desarrollador. Cifrar archivos binarios gigantes (como fotos de alta resolución de varios megabytes) aplicando todo el peso del KDF dual (los 60MB de RAM de Argon2id más el CPU de PBKDF2) y luego cifrarlo doble con ChaCha20 y AES, causaría que guardar tu nota tardara varios segundos. Esto haría que usar la aplicación fuera frustrante y lento, arruinando la experiencia de usuario (UX).

Para resolver esto sin vender tu privacidad, bifurquĂ© la lĂłgica dentro de CryptoService, creando una “vĂ­a rápida” pero increĂ­blemente blindada, solo para las imágenes:

C#

// Dentro del proceso específico para cifrar imágenes
byte[] salt = RandomNumberGenerator.GetBytes(SALT_SIZE);
byte[] nonce = RandomNumberGenerator.GetBytes(NONCE_SIZE);

// 1. Derivación de clave optimizada y rápida
key = PBKDF2_SHA256(passwordBytes, salt, PBKDF2_IMG_ITERATIONS, KEY_SIZE);

// 2. Cifrado Ăşnico con AES-GCM (RapidĂ­simo por estar integrado en el procesador)
cipherWithTag = AesGcmEncrypt(imageBytes, key, nonce);

Las diferencias arquitectĂłnicas para tus fotos:

  1. KDF Simplificado: Para la foto, no uso Argon2id. Utilizo exclusivamente PBKDF2-SHA256 y fijo las iteraciones internamente en 100003 (elegí un número primo para evitar patrones predecibles). Es rápido, pero mantiene el muro mínimo de los 100 mil intentos.
  2. Cifrado Único Directo: No paso la foto por ChaCha20. Uso únicamente AES-256-GCM. ¿Por qué? Porque los procesadores modernos (como los Intel Core o AMD Ryzen) traen bloques dedicados por hardware exclusivamente a procesar instrucciones AES (AES-NI). Esto permite que mi código cifre gigabytes de imágenes en una fracción de segundo.
  3. Flujos en Memoria: Cuando abres la nota para ver tu foto, FoxNotes nunca crea un archivo temporal en tu disco duro para mostrarla. La foto se descifra directamente en un “flujo de memoria” (MemoryStream) invisible.

C#

// Creo un espacio seguro en RAM
byte[] safeStreamBytes = new byte[imageBytes.Length];
Buffer.BlockCopy(imageBytes, 0, safeStreamBytes, 0, imageBytes.Length);

// Devuelvo la imagen directo a la interfaz desde la memoria RAM
return new MemoryStream(safeStreamBytes, 0, safeStreamBytes.Length, true, true);

Esto te garantiza que la foto descifrada solo existe en el interior de la memoria RAM, y desaparece de la existencia en el instante en que cierras la nota. Ninguna herramienta forense policial podrá recuperar miniaturas de tus fotos analizando tu disco duro apagado.

6. Higiene de Memoria Extrema: El arte de no dejar ni un rastro (ZeroMemory)

Puedo programar la criptografĂ­a más impenetrable del mundo, pero todo es inĂştil si la aplicaciĂłn deja “basura” confidencial tirada en la memoria de tu ordenador. Durante los pesados procesos matemáticos de derivar tus claves y cifrar tus textos, genero muchĂ­simos datos temporales: tu contraseña en formato de bytes, las sales matemáticas, los resultados intermedios de Argon2id, las llaves maestras divididas y el texto limpio que acabas de escribir.

En un entorno normal de C#, todos estos datos quedarĂ­an ahĂ­ tirados, a merced del GC (el Recolector de Basura). El peligro real es que, si tu sistema operativo se queda sin memoria fĂ­sica (RAM) porque abriste muchas pestañas en el navegador, Windows podrĂ­a agarrar esa “basura” y guardarla en tu disco duro (en el famoso archivo de paginaciĂłn o pagefile.sys). Si alguien roba tu laptop apagada, podrĂ­a extraer ese archivo de paginaciĂłn y recuperar tus claves maestras, burlando todas las cajas fuertes de las que hemos hablado.

Para bloquear esta fuga de información mortal, FoxNotes aplica algo que yo llamo la Doctrina de Higiene Extrema, haciendo un uso obsesivo de un método auxiliar que llamé Wipe. Este método activa una función a nivel del procesador llamada CryptographicOperations.ZeroMemory.

C#

private static void Wipe(byte[]? array)
{
    if (array != null)
        // Sobrescribe fĂ­sicamente la celda de memoria con ceros
        CryptographicOperations.ZeroMemory(array);
}

La Doctrina de los Bloques finally

Fíjate en esta estructura de control que uso en el método maestro cuando descifras tu nota (DecryptTextAsync):

C#

try
{
    // ... aquí ocurre toda la matemática compleja para abrir tu nota ...
}
catch (Exception)
{
    // Si hay un error, lo oculto con un mensaje genérico para no darle pistas al hacker
    throw new CryptographicException("Decryption failed: Integrity error or invalid credentials.");
}
finally
{
    // Limpieza obligatoria, pase lo que pase
    Wipe(hashA); 
    Wipe(hashB); 
    Wipe(masterKey); 
    Wipe(key1); 
    Wipe(key2); 
    Wipe(cipher1); 
    Wipe(plainBytes); 
    Wipe(aad);
}

Ese bloque finally al final del código es tu seguro de vida digital. Garantiza que, sin importar si lograste abrir tu nota, o si te equivocaste de contraseña, o si el archivo estaba corrupto y la app explotó internamente, todos los vectores críticos de la operación son sobrescritos con ceros a nivel físico en tu procesador.

Purgó las dos mitades de la llave, las matemáticas de Argon2id y tu texto plano convertido en bytes. Lavo la pizarra antes de devolverle el control al resto de la aplicación. Esta técnica paranoica de higiene de memoria es un estándar requerido en módulos criptográficos de agencias de inteligencia (como la norma FIPS 140-2), pero es algo que excepcionalmente rara vez verás implementado en una aplicación de toma de notas para usuarios cotidianos. Yo lo incluyo por defecto y porque la esquizofrenia me lo demanda 🫠.

7. Contexto Activo: Rendimiento fluido sin comprometer tu seguridad

Para terminar, quizás te estĂ©s preguntando algo lĂłgico: Si cada vez que toco una tecla, FoxNotes tiene que usar 60 Megabytes de RAM y calcular cien mil operaciones para cifrar… Âżpor quĂ© mi computadora no colapsa ni se congela cuando escribo?

La aplicación tiene que guardar tus cambios en vivo y renderizar la vista previa de tus apuntes al instante. Si aplicara el proceso matemático completo en cada letra que escribes, tu máquina se detendría por completo.

La solución de ingeniería arquitectónica que implementé en mi CryptoService.cs para esto se llama el Contexto Activo (ActiveNoteContext).

C#

// Método que crea la sesión segura en memoria
public ActiveNoteContext CreateContext(byte[] passwordBytes, byte[] salt, int iterations)

Cuando haces clic para desbloquear tu cuaderno o tu nota y proporcionas la contraseña correcta, el sistema hace el trabajo pesadísimo (Argon2id y PBKDF2) una única vez. El resultado final (las llaves maestras key1 y key2) las retengo suspendidas en una pequeña bóveda de la memoria volátil a través de esta clase encapsulada (ActiveNoteContext). Inmediatamente después, destruyo tu contraseña original.

Mientras tengas la nota abierta, FoxNotes usará los métodos especiales EncryptTextWithContextAsync y DecryptTextWithContextAsync. Estos métodos son como un pase VIP: se saltan el cobro pesado de CPU y RAM y van directo a las cajas fuertes veloces de ChaCha20 y AES-GCM usando las llaves suspendidas.

Gracias a esto, FoxNotes puede cifrar, descifrar y autoguardar megabytes enteros de tu texto en microsegundos, asegurando que tu experiencia al escribir sea suave, rápida y en tiempo real, pero sin rebajar jamás la seguridad de tu clave. En el instante exacto en que decides cerrar la nota o bloquear la aplicaciĂłn, el mĂ©todo ZeroMemory entra en acciĂłn, el “Contexto Activo” es asesinado y purgado de la memoria, y tu bĂşnker queda completamente sellado de nuevo, esperando tu prĂłxima sesiĂłn de escritura.

ConclusiĂłn

Como desarrollador, creo que el diseño criptográfico de FoxNotes no es simplemente agarrar unas cuantas librerĂ­as estándar de programaciĂłn y pegarlas con cinta Scotch. He construido esta arquitectura desde cero y siempre asumiendo el peor escenario posible (Un profe de Progra mĂ­o decĂ­a que “debemos programar como si el usuario fuera un asesino en serie y sabe donde vives”), pensando en un modelo de amenaza hostil.

  1. He protegido tus intenciones aislando tu contraseña del recolector de basura de Windows.
  2. Te he defendido contra granjas de servidores y hardware masivo forzando el agotamiento de sus recursos mediante la combinaciĂłn de Argon2id y PBKDF2 trabajando juntos.
  3. Aseguré la total impenetrabilidad de tus palabras combinando la confusión geométrica pura de ChaCha20 con la validación de integridad inquebrantable de AES-256-GCM.
  4. Y lo más importante de todo: entiendo y acepto que la memoria de un ordenador es un entorno peligroso y sucio, y mi código asume la responsabilidad inquebrantable de borrar sus propias huellas matemáticas tras cada operación.

Con FoxNotes, no tienes que confiar en mí, tienes que confiar en la matemática y en el código. He transformado una simple carpeta en tu computadora en una bóveda inexpugnable, para entregarte a ti, y solo a ti, el verdadero significado de la soberanía de tus datos. Sólo no pierdas la contraseña, porque ni yo ni nadie podrá abrir tu nota.

Scroll to Top