Experimento de restauración de copias cifradas: solo datos artificiales Fecha de observación: 2026-09-03 Qué se midió ------------ El experimento utiliza restic 0.19.1, Python 3.12.10 y Windows 11 amd64. Genera doce archivos de siete grupos: texto UTF-8, JSON, CSV, XML, ZIP, WAV y TOML. No contiene documentos, fotografías, grabaciones ni credenciales de personas reales. El conjunto normal suma 2.330 bytes. Es un diseño de prueba local, no una comparación ni una calificación de productos. Las ejecuciones de desarrollo y la ejecución final produjeron las mismas seis filas. No son pruebas independientes en equipos diferentes. El repositorio usa el formato 2, la compresión predeterminada de restic (auto) y no utiliza caché. El script obtiene el identificador completo de cada instantánea tras una copia correcta. La restauración usa ese ID fijo y la subcarpeta artificial /source, nunca el identificador especial latest. El destino siempre es nuevo, vacío y está dentro del directorio recién creado para el experimento. También se establece --overwrite never. El manifiesto de los doce archivos previstos se prepara antes de aplicar la exclusión de S4. La referencia de la revisión actual necesaria en S5 se genera antes de guardar la versión antigua. En S6, el manifiesto describe el JSON deliberadamente inválido y registra su error de lectura antes de respaldarlo. La lista de una instantánea incompleta no se usa como lista de todo lo que se pretendía conservar. Cada prueba responde a una pregunta distinta: * restic check: ¿supera el repositorio la comprobación estructural ordinaria? * restic check --read-data: ¿supera la lectura de todos los datos almacenados? * restic restore: ¿termina la extracción con código de salida 0? * Inventario: ¿están las rutas previstas, sin archivos inesperados? * SHA256: ¿coinciden los archivos previstos con la referencia independiente? * Lector de formato: ¿se pueden leer con el lector estándar indicado? Resultados observados --------------------- Caso check read-data restore rutas SHA256 lectura correcta/probados S1 0 0 0 12/12 12/12 12/12 S2 12 12 12 0/12 0/12 sin pruebas (0 archivos) S3 0 1 1 11/12 11/12 11/11 S4 0 0 0 11/12 11/12 11/11 S5 0 0 0 12/12 11/12 12/12 S6 0 0 0 12/12 12/12 11/12 El código 0 indica que la operación terminó correctamente. En esta ejecución, 12 indica una contraseña pública de prueba incorrecta; 1, un error de datos, lectura o restauración. El JSON y el registro de comandos mantienen separadas las operaciones y sus diagnósticos. Un 0 no demuestra que se haya satisfecho toda la necesidad de recuperación de una persona. S1: Entrada artificial sin cambios. Coinciden rutas y bytes; todas las pruebas de formato terminan correctamente. S2: Contraseña artificial incorrecta contra una copia del repositorio S1. No se recuperan archivos. Se prueba el rechazo de esa contraseña, no la ausencia de cualquier otra clave o vía de recuperación. S3: Se altera un byte cifrado de un bloque de datos de una copia desechable del repositorio S1. El bloque de documents/records.json se identifica en el índice mediante su hash conocido. Se cambia el byte situado tras su nonce de 16 bytes, sin modificar el tamaño ni la cabecera del pack. La comprobación ordinaria termina correctamente; la lectura completa y la restauración fallan. Se recuperan once archivos. results.json conserva los identificadores, la posición modificada, los hashes y el archivo ausente. Otros daños pueden detectarse en la comprobación ordinaria; este resultado se limita al daño introducido. S4: Se excluye documents/contacts.csv después de preparar la lista completa. Las operaciones de restic terminan correctamente, pero la comparación con lo previsto solo encuentra 11 de 12 rutas y hashes. S5: Se restaura la instantánea antigua aunque existe otra más reciente. documents/status.json contiene la revisión 1, no la revisión 2 requerida. Los doce archivos se leen, pero once coinciden con la referencia actual. Los doce coinciden con la referencia antigua conservada por separado. Es una restauración correcta de la versión equivocada para el objetivo, no daño causado por restic. S6: documents/records.json ya contiene JSON inválido antes de la copia. synthetic-manifests.json registra ese error de origen. Todos los bytes restaurados coinciden, pero el lector de JSON vuelve a rechazar el archivo. La restauración no creó el defecto. Alcance de las pruebas de lectura -------------------------------- Solo se prueban los archivos presentes. Los ausentes se cuentan en el inventario y no se consideran lecturas correctas. TXT usa decodificación UTF-8 estricta; JSON, json.loads; CSV, csv.reader(strict) y comprobación del número de columnas; XML, ElementTree.parse; ZIP lee todos los elementos y comprueba sus CRC; WAV lee las tramas de audio declaradas y comprueba su longitud; TOML usa tomllib.loads. Son operaciones reales de lectura y análisis, no meras comprobaciones de la extensión. No demuestran que una aplicación de escritorio represente todas las funciones ni que el contenido satisfaga las necesidades reales de alguien. Material publicado ------------------ restore-lab.py Código final; solo biblioteca estándar de Python. results.csv Resultados numéricos resumidos. results.json Resultados por archivo, IDs, procedencia del ejecutable, hash del script y daño introducido. synthetic-manifests.json Referencias previas y lectura de los originales. command-log.json Comandos, códigos de salida, stdout y stderr. Se ocultan rutas del experimento, nombre de la cuenta de ejecución y campos de fecha y hora. Se conservan los resultados operativos. lab-readme.txt Método y límites, en español. Los datos y el código mantienen el mismo contenido en todas las versiones lingüísticas. El registro de comandos está depurado: no es una captura intacta del terminal. Reproducción en Windows amd64 ---------------------------- Necesitas Python 3.11 o posterior y el ZIP oficial indicado. La ejecución registrada utilizó Python 3.12.10. Guarda restore-lab.py en una carpeta de trabajo nueva. Descarga el ZIP y compara su SHA256 con SHA256SUMS de la publicación oficial. El script exige ambos hashes indicados a continuación. No descarga archivos ni requiere instalar restic en todo el sistema. Publicación: https://github.com/restic/restic/releases/tag/v0.19.1 ZIP: https://github.com/restic/restic/releases/download/v0.19.1/restic_0.19.1_windows_amd64.zip Sumas oficiales: https://github.com/restic/restic/releases/download/v0.19.1/SHA256SUMS SHA256 del ZIP: da948ad707ed690426473aaba2046cd61f8f90f6f0e7dab6be0d5796531de67d SHA256 del ejecutable extraído: b0dd1fd21eea5d8fe1325f55f7118213c21f36de8a261e04c0624a5ab9fd7830 Versión observada: restic 0.19.1 compiled with go1.26.4 on windows/amd64 El hash del ZIP se contrastó con las sumas obtenidas por HTTPS de la misma publicación oficial. No se verificó por separado la firma de la publicación. Desde la carpeta de trabajo nueva, ejecuta en PowerShell: python .\restore-lab.py --restic-zip .\restic_0.19.1_windows_amd64.zip El script crea una carpeta c07-restore-lab-* dentro de esa carpeta de trabajo y muestra LAB_ROOT. No acepta repositorios, orígenes ni destinos existentes. Rechaza enlaces simbólicos y puntos de reanálisis de Windows, incluidas junctions. Lee el ZIP como bytes y extrae únicamente el ejecutable nombrado. La alteración destructiva se limita a la copia S3 recién creada. No hay limpieza automática ni operaciones sobre datos reales. Las cadenas PUBLIC-SYNTHETIC-LAB-ONLY... son datos públicos de prueba. No son secretos y no deben proteger archivos reales. Los procesos de restic las reciben en lugar de heredar ajustes RESTIC_* existentes. Sus archivos temporales quedan bajo la nueva raíz del experimento. No se modifican variables globales del entorno ni la configuración de VPN. Los resultados quedan en LAB_ROOT; no se copian automáticamente a una carpeta de publicación. Cada ejecución crea un directorio nuevo. Las claves aleatorias, los IDs de instantáneas y packs y los tiempos varían. El archivo dañado se fija por su hash conocido. El script calcula su propio hash al inicio y lo vuelve a comprobar al terminar: si cambia durante la ejecución, esa ejecución no puede finalizar como registro completo. Límites ------- No se midieron repositorios grandes, velocidad de restauración, tasas de fallo de discos, vida de los soportes, resistencia de copias desconectadas o en otras ubicaciones, recuperación de cuentas en la nube, custodia de credenciales, sistemas operativos completos, permisos, listas de control de acceso, flujos de datos alternativos, representación en aplicaciones ni compatibilidad futura de formatos. Las pruebas de lectura se limitan a estos archivos y lectores. No se garantiza la recuperación de una copia personal. Documentación oficial pertinente ------------------------------- https://restic.readthedocs.io/en/stable/045_working_with_repos.html https://restic.readthedocs.io/en/stable/050_restore.html https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html Los resultados observan la versión 0.19.1. El manual stable puede cambiar; por eso se conservan versión, URL de publicación, hashes, comandos y código. Material didáctico añadido (2026-09-13) -------------------------------------- El nuevo script compara el registro de una ejecución con la referencia publicada. comparison-readme.txt explica la preparación, los resultados, los límites y la generación de la figura. Ese suplemento técnico y la figura independiente están en inglés.