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Ă:
- Transforma el
SecureStringque estaba cifrado en un puntero (IntPtr), que no es más que una dirección hacia un bloque de memoria no administrada. - Copia los caracteres a un arreglo temporal
char[]administrado, pero solo durante el instante estrictamente necesario para convertirlo al formato de bytes (UTF-8). - El Punto CrĂtico: Inmediatamente despuĂ©s de obtener los bytes, utilizo
Array.Clearpara sobrescribir ese arreglo temporal de caracteres con ceros. - 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), utilizoMarshal.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:
- 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.
- 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:
- 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. - 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.
- 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.
- He protegido tus intenciones aislando tu contraseña del recolector de basura de Windows.
- 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.
- 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.
- 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.
