Los archivos se cifran antes de salir de tu dispositivo. Los dispositivos se sincronizan directamente entre sí, o a través de cualquier cosa que pueda guardar bytes: un bucket de S3, una carpeta local, un directorio que iCloud o Dropbox transporten. Ninguno ve nombres ni contenidos, y ninguno necesita bloqueos ni actualizaciones atómicas.
Escrito en Rust. CLI, montaje FUSE, interfaz web y enlaces para C, Python y Go.
i/d7a1…/000412-9f3c…-18204 i/2b90…/000098-71e0…-6112 p/3f/3f8a…-6291456 p/c2/c2d4…-5833728 n/0007-e41b…-2097152 r/d7a1…-epoch3
docs/ contract-2026.pdf 2 versiones notes.md 2 heads en conflicto photos/ 2026-09/IMG_4471.heic se obtiene al leer projects/cipherfs/ README.md papelera: old-drafts/ (14 archivos)
A la izquierda, nombres de objeto formados por un id de dispositivo, un número de secuencia, una longitud y un hash del texto cifrado. A la derecha, el árbol de archivos que muestra un dispositivo tras descifrar, con el número de versiones, los conflictos y la papelera. Entre ambos no hay ningún servidor.
El contenido, los nombres de archivo y los metadatos sensibles se cifran antes de salir del dispositivo. La lectura verifica la integridad; una contraseña incorrecta, una manipulación o un daño fallan de forma explícita. Las claves y el texto en claro nunca llegan a registros ni almacenes.
Los cambios hechos sin conexión se sincronizan al recuperarla. Las transferencias interrumpidas se reintentan, y una transferencia repetida nunca vuelve a aplicar ni resucita una versión antigua. Las ediciones concurrentes eligen la versión actual con una sola regla; las demás se conservan.
Los archivos pequeños siguen siendo baratos. Los grandes se trocean, se transmiten en flujo y se obtienen por rango de bytes. El usuario nunca elige un modo, y cruzar un umbral de tamaño nunca cambia la semántica.
El cifrado, el modelo de archivos, las transacciones de almacenamiento y las reglas de sincronización viven en el núcleo. CLI, montaje, interfaz web y enlaces de lenguaje solo adaptan el acceso. No mantienen su propia base de datos ni inventan reglas.
Cada dispositivo guarda el índice compartido completo. El contenido se sincroniza a todos los dispositivos por defecto; un teléfono o un portátil con poco espacio puede ser un dispositivo parcial que solo conserva las carpetas fijadas y lo leído recientemente.
Los dispositivos se conectan entre pares. Los almacenes solo guardan objetos cifrados. El historial, la papelera y los conflictos son vistas de una misma cadena de versiones compartida, visible en todos los dispositivos. Cada dispositivo tiene identidad propia y puede revocarse.
Cada archivo tiene una identidad estable; su ruta es solo un atributo. Cada dispositivo añade entradas a su propio registro firmado, y los demás verifican la pertenencia, la cadena de hashes y las dependencias causales antes de fusionar. Un borrado es una versión tombstone, un movimiento es una versión con otra ruta, y un conflicto son dos o más heads sin orden causal entre sí.
Los directorios y los montajes muestran solo la versión actual; no se escriben copias de conflicto. Una versión sale del historial compartido únicamente por una purga explícita o por la política de retención del repositorio (365 días por defecto). Primero pasa 30 días en estado pendiente, durante los cuales cualquier dispositivo puede cancelarla.
Clientes que poseen las claves del repositorio y leen texto en claro. Cada uno tiene un par de claves de larga duración, un nombre legible y un rol completo o parcial. Un dispositivo nuevo se empareja con un código corto o un código QR; sin ningún dispositivo existente presente, se une con la clave de recuperación.
Solo necesitan cuatro operaciones: escribir un objeto inmutable, leer por nombre, listar por prefijo, borrar. Los objetos se direccionan por contenido y solo se añaden, empaquetados de 4 a 8 MiB. Un objeto que no ha llegado por completo está «todavía no aquí», nunca «dañado».
Las claves de contenido derivan de una época de claves. Revocar un dispositivo abre una nueva época cuya clave se envuelve solo para los dispositivos restantes. La contraseña protege únicamente la máquina local; si se olvida, se restablece con la clave de recuperación y el dispositivo conserva su identidad.
Una máquina siempre encendida es el dispositivo completo. El Mac es un dispositivo parcial con un montaje. Conserva solo las carpetas fijadas y el contenido leído recientemente; todo lo demás sigue apareciendo en el Finder y se obtiene del dispositivo completo o de un almacén al abrirlo. Superado el presupuesto de caché, el contenido confirmado en otro lugar se libera automáticamente. Las escrituras locales sin sincronizar y los archivos abiertos nunca se liberan.
Verificado en macOS 27 con FUSE-T: el montaje lleva .metadata_never_index, está excluido de Time Machine, recorrer todas las carpetas en el Finder dejó la caché sin cambios, y leer un archivo no disponible sin conexión falla de inmediato en lugar de quedarse colgado.
No como versión estable. Los requisitos confirmados están implementados y cada uno tiene evidencia de aceptación, pero el formato en disco y la API todavía pueden cambiar, no ha habido auditoría de seguridad externa y nunca se ha hecho una promesa de compatibilidad. Hoy sirve para el autor y unas pocas personas que acepten que el formato cambie.
Resultados de verificación a 12 de octubre de 2026. Los recuentos son ejecuciones reales por combinación de features.
| Comprobación | Resultado | |
|---|---|---|
| Pruebas Rust en el host, features por defecto | 672 pasan / 0 fallan | pasa |
| Pruebas Rust en el host, todas las features | 700 pasan / 0 fallan | pasa |
| Ejecución en contenedor, Rust | 754 pasan / 0 fallan / 2 ignoradas | pasa |
| Runtime C / Python / Go race | 15 / 10 / paquete completo | pasa |
| Compilación del frontend, prueba de humo web | 24 comprobaciones | pasa |
| Montaje parcial FUSE-T real, navegación en Finder | caché 54.288 → 54.288 B | pasa |
| Matriz de aceptación de requisitos | R01–R62 asociados a pruebas | hecho |
La contraseña se toma de CIPHERFS_PASSWORD o de una petición interactiva. Las credenciales de S3 se leen de variables de entorno y nunca se escriben en el índice compartido.
cipherfs init --path ~/vault cipherfs put --vault ~/vault --source ./notes.txt --target docs/notes.txt cipherfs store add directory --vault ~/vault --dir ~/Library/CloudStorage/Dropbox/cfs cipherfs sync directory --vault ~/vault --store-dir ~/Library/CloudStorage/Dropbox/cfs cipherfs role set partial --vault ~/vault --read-cache-bytes 2147483648 cipherfs pin add --vault ~/vault --path docs cipherfs mount --vault ~/vault --mount-point ~/CipherFS --background cipherfs devices list --vault ~/vault cipherfs safe-to-remove --vault ~/vault cipherfs history --vault ~/vault --path docs/notes.txt cipherfs export --vault ~/vault --target ~/plain-copy --history
Las aplicaciones Rust usan SyncedVault: put, put_from_reader, get, get_to_writer, get_range, delete, list. Una escritura correcta significa que los datos son duraderos localmente; una tarea en segundo plano se encarga de la sincronización, la reconexión y los reintentos. El uso de memoria no depende del tamaño del objeto.
| Propósito | Algoritmo |
|---|---|
| AEAD de contenido | XChaCha20-Poly1305 (opcional AES-256-GCM, ChaCha20-Poly1305) |
| Troceado | FastCDC, mín/med/máx 1 / 4 / 8 MiB, unidad máxima 16 MiB |
| Direccionamiento por contenido | BLAKE3 |
| Identidad del dispositivo | firmas ed25519, envoltura X25519, también es el id de nodo P2P |
| Contraseña local | Argon2id envuelve el material de claves local; nunca se sincroniza |
| Transporte | QUIC (Iroh); HTTPS hacia los almacenes cuando hace falta |