Copias de seguridad

age o gpg para cifrar una copia con tar: tamaño, errores y qué se rompe

Publicado el 25 de octubre de 2026Última revisión: 25 de octubre de 20265 min de lectura

Resultado de la prueba

age no comprime (26 241 480 bytes frente a 21 048 019 de gpg) y tardó 88 ms frente a 860 ms; con un byte dañado, age y tar fallan los dos, mientras que con gpg tar devolvió 0.

Contenido

Este artículo no contiene enlaces de afiliado.

Si ya leíste tar + gpg, la pregunta siguiente es si age, más moderno y con menos opciones, lo mejora. Se probaron las dos herramientas sobre la misma carpeta.

Condiciones: age 1.1.1 (paquete de Ubuntu) y gpg del sistema, 20 ficheros aleatorios de 1 MiB y un log repetitivo de 5 MiB (25 604 KiB), claves y contraseñas desechables. Script completo al final del artículo. No se probó rendimiento con carpetas grandes, ni Windows o macOS. La prueba de age usa un par de claves porque age -p (contraseña) pide un terminal y no se puede automatizar en un script.

Tamaño y tiempo

tar + gpg (AES256, contraseña) tar + age (clave pública)
Tamaño 21 048 019 bytes 26 241 480 bytes
Tiempo de cifrado 860 ms 88 ms

La diferencia de tamaño viene de que gpg comprime antes de cifrar y age no: el log repetitivo ocupó mucho menos con gpg. Si tus datos se comprimen bien, con age tendrás que comprimir tú (tar -czf - carpeta | age ...), cosa que esta prueba no midió. El tiempo también está afectado por esa compresión, así que no es una comparación de velocidad de cifrado pura.

Ninguna de las dos hace copias incrementales: cada copia nueva es completa.

Cuando algo va mal

Lo que cambia en la práctica

Veredicto

Para una carpeta que archivas una vez, cualquiera de las dos sirve; elige age si prefieres claves y mensajes de error simples, y gpg si quieres compresión integrada. Para datos que cambian, usa una herramienta con copias incrementales como restic, y prueba siempre la restauración.

Script completo

test-age-tar.sh:

#!/bin/bash
# tar + age (key pair) backup: size, time, wrong key, corruption, truncation. Usage: test-age-tar.sh WORKDIR. Throwaway keys.
W=$1; rm -rf "$W"; mkdir -p "$W/data"; cd "$W"
for i in $(seq 1 20); do head -c 1048576 /dev/urandom > data/f$i.bin; done; yes "linea de texto repetida" | head -c 5242880 > data/log.txt
echo "origen: $(du -sk data | cut -f1) KiB"; age --version
age-keygen -o clave.txt 2>/dev/null; age-keygen -o otra.txt 2>/dev/null; PUB=$(age-keygen -y clave.txt)
t(){ local s=$(date +%s%N); "$@"; echo "[tiempo: $(( ($(date +%s%N)-s)/1000000 )) ms]" >&2; }
echo "== tar + age"; t bash -c 'tar -cf - data | age -r '"$PUB"' -o copia.tar.age'
ls -l copia.tar.age | awk '{print $5" bytes"}'
echo "== restaurar"; mkdir r; age -d -i clave.txt copia.tar.age | tar -xf - -C r; echo "ficheros: $(find r -type f | wc -l)"
echo "== clave equivocada"; age -d -i otra.txt copia.tar.age >/dev/null 2>err1; echo "exit=$?"; tail -2 err1
echo "== un byte dañado en el medio"; cp copia.tar.age dan.age; printf '\xff' | dd of=dan.age bs=1 seek=10000000 conv=notrunc 2>/dev/null
age -d -i clave.txt dan.age 2>err2 | tar -tf - >/dev/null 2>&1; echo "exit age/tar=${PIPESTATUS[0]}/${PIPESTATUS[1]}"; tail -2 err2
echo "== fichero truncado a la mitad"; head -c 7000000 copia.tar.age > tr.age
age -d -i clave.txt tr.age 2>err3 | tar -tf - >/dev/null 2>&1; echo "exit age/tar=${PIPESTATUS[0]}/${PIPESTATUS[1]}"; tail -2 err3

test-gpg-tar.sh:

#!/bin/bash
# tar + gpg symmetric backup: size, time, wrong passphrase, corruption. Usage: test-gpg-tar.sh WORKDIR. Throwaway passphrase.
W=$1; rm -rf "$W"; mkdir -p "$W/data"; cd "$W"
for i in $(seq 1 20); do head -c 1048576 /dev/urandom > data/f$i.bin; done; yes "linea de texto repetida" | head -c 5242880 > data/log.txt
echo "origen: $(du -sk data | cut -f1) KiB"
t(){ local s=$(date +%s%N); "$@"; echo "[tiempo: $(( ($(date +%s%N)-s)/1000000 )) ms]" >&2; }
echo "== tar + gpg AES256"; t bash -c 'tar -cf - data | gpg --batch --yes --pinentry-mode loopback --passphrase prueba-desechable --symmetric --cipher-algo AES256 -o copia.tar.gpg 2>/dev/null'
ls -l copia.tar.gpg | awk '{print $5" bytes"}'
echo "== día 2: cambia un fichero y se vuelve a hacer todo"; echo cambio >> data/f1.bin
t bash -c 'tar -cf - data | gpg --batch --yes --pinentry-mode loopback --passphrase prueba-desechable --symmetric --cipher-algo AES256 -o copia2.tar.gpg 2>/dev/null'
ls -l copia2.tar.gpg | awk '{print $5" bytes"}'
echo "== restaurar"; mkdir r; gpg --batch --pinentry-mode loopback --passphrase prueba-desechable -d copia.tar.gpg 2>/dev/null | tar -xf - -C r; echo "ficheros: $(find r -type f | wc -l)"
echo "== passphrase mala"; gpg --batch --pinentry-mode loopback --passphrase mala -d copia.tar.gpg >/dev/null 2>/tmp/gpgerr; echo "exit=$?"; tail -1 /tmp/gpgerr
echo "== un byte dañado en el medio"; cp copia.tar.gpg dan.gpg; printf '\xff' | dd of=dan.gpg bs=1 seek=10000000 conv=notrunc 2>/dev/null
gpg --batch --pinentry-mode loopback --passphrase prueba-desechable -d dan.gpg 2>/tmp/gpgerr2 | tar -tf - >/dev/null 2>&1; echo "exit gpg/tar=${PIPESTATUS[0]}/${PIPESTATUS[1]}"; tail -2 /tmp/gpgerr2
echo "== comparación: ficheros que cambian entre copias (cmp de las dos .gpg)"; cmp copia.tar.gpg copia2.tar.gpg | head -1