Verifica manifiestos de artefactos con b2sum y GNU Parallel
Usa b2sum de GNU para registrar un conjunto completo de artefactos y luego
verifícalo sin regenerar sus valores esperados. Esta guía calcula en paralelo los hashes de un
pequeño directorio de copias de seguridad, reemplaza el manifiesto solo después de que todos los
hashes se calculen correctamente y propaga los fallos de verificación a una shell o tarea de CI.
Un resumen criptográfico por sí solo no permite determinar quién creó un archivo: obtén la suma de verificación esperada a través de un canal de confianza, como una versión autenticada o un manifiesto firmado, en lugar de descargar tanto el archivo como su suma de verificación de una fuente no confiable.
Elige el formato de suma de verificación correspondiente
b2sum de GNU
usa BLAKE2b-512 de forma predeterminada, expresado en 128 caracteres hexadecimales. Usa el mismo
algoritmo y la misma longitud de resumen que los valores esperados. BLAKE2s y SHA-256 son formatos
diferentes; si quien publica proporciona SHA-256, verifica con sha256sum en lugar
de inventar una referencia BLAKE2 a partir de la descarga.
Esta demostración crea una referencia local a partir de archivos conocidos. En un flujo de publicación de versiones, genera el manifiesto del lado del productor de confianza una vez que los artefactos estén completos y luego protege su origen y contenido. Alguien que pueda reemplazar tanto los artefactos como los valores esperados puede hacer que la verificación sea exitosa.
Comprueba los requisitos previos de Linux
Usa Linux con Bash, GNU coreutils, GNU findutils, GNU Parallel y Python 3. En Debian o Ubuntu,
los paquetes correspondientes son bash, coreutils, findutils, parallel y python3.
GNU Parallel se instala por separado; otro comando llamado parallel no lo
sustituye. Comprueba su disponibilidad antes de crear el directorio de la demostración:
bash --version && b2sum --version && find --version && parallel --version && python3 --version
El ejemplo se probó con Bash 5.3.15, coreutils 9.11, findutils 4.11.0, GNU Parallel 20240222 y Python 3.14.7. Python solo crea los archivos de la demostración y no necesita paquetes de terceros. Este es un flujo de trabajo local para Linux, no una guía para macOS o Windows.
Crea un pequeño conjunto de artefactos
Comienza en un directorio que controles. Este comando entra en un directorio nuevo y se niega a reutilizar uno que ya exista:
mkdir -- integrity-demo && cd -- integrity-demo
Mantén los demás archivos y comandos en integrity-demo.
Guarda lo siguiente como make-fixture.py:
from pathlib import Path
root = Path('backups')
root.mkdir()
(root / 'archive').mkdir()
samples = {
'app.tar': b'first release\n',
'archive/app.tar': b'other release\n',
'empty.tar': b'',
'-draft.tar': bytes([0, 255, 16, 10]),
'café copy.tar': b'Unicode name\n',
'line\nbreak.tar': b'newline name\n',
}
for name, content in samples.items():
(root / name).write_bytes(content)
Ejecútalo una vez:
python3 -I make-fixture.py
Estos seis archivos pequeños permiten probar contenido vacío y binario, nombres base duplicados,
espacios, Unicode y un salto de línea en un nombre de archivo. Son bytes de ejemplo con el sufijo
.tar, no contenedores tar reales.
El generador rechaza un directorio backups existente. Si la preparación se
interrumpe, inspecciona el directorio parcial e inicia una demostración nueva en un directorio sin
usar; volver a ejecutar el generador no reparará ni sobrescribirá los archivos anteriores.
Genera un manifiesto completo
Guarda esto como hash-backups.sh. Ejecútalo como un script de Bash guardado en lugar
de pegarlo en tu shell:
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
umask 077
if (( $# != 1 )) || [[ -z $1 ]]; then
printf 'Usage: bash hash-backups.sh BACKUP_DIR\n' >&2
exit 2
fi
backupDir=$1
if [[ $backupDir != /* ]]; then
backupDir=./$backupDir
fi
if [[ ! -d $backupDir ]]; then
printf 'Not a directory: %s\n' "$backupDir" >&2
exit 2
fi
tempDir=$(mktemp -d .checksums.XXXXXX)
trap 'rm -rf -- "$tempDir"' EXIT
find "$backupDir" -type f -name '*.tar' -print0 > "$tempDir/files.nul"
if [[ ! -s $tempDir/files.nul ]]; then
printf 'No .tar files selected in %s\n' "$backupDir" >&2
exit 1
fi
sort -z "$tempDir/files.nul" |
parallel --plain --will-cite --tmpdir "$tempDir" -0 --jobs 4 \
--keep-order --halt now,fail=1 b2sum -- {} > "$tempDir/checksums.b2"
test -s "$tempDir/checksums.b2"
mv -fT -- "$tempDir/checksums.b2" checksums.b2
Ejecuta el productor:
bash hash-backups.sh backups
Selecciona de forma recursiva los archivos regulares con el sufijo en minúsculas
.tar, sin seguir entradas de enlaces simbólicos. GNU Parallel ejecuta
hasta cuatro tareas de cálculo de hashes, agrupa su salida y conserva el orden de entrada ordenado.
Su
opción --plain ignora los perfiles personales
y la configuración de PARALLEL, mientras que --halt now,fail=1
detiene la ejecución si falla el cálculo de un hash. Una selección vacía, un fallo al recorrer el
directorio o un fallo en el cálculo de un hash hace que el script termine con un estado distinto de
cero antes de reemplazar checksums.b2.
El directorio temporal está junto al destino, por lo que el mv final
publica el manifiesto completo mediante un cambio de nombre en el mismo sistema de archivos.
Una nueva ejecución exitosa reemplaza el manifiesto anterior; los fallos lo dejan intacto y eliminan
los archivos temporales. Ejecuta un solo productor a la vez y mantén el directorio de artefactos sin
cambios mientras se recorre, se calculan los hashes o se verifica. Esto no es una instantánea del
sistema de archivos.
Verifica los archivos registrados
Ejecuta el consumidor desde el mismo directorio integrity-demo, sin modificar
checksums.b2:
b2sum --check --strict --quiet checksums.b2 && printf 'All recorded files match checksums.b2\n'
All recorded files match checksums.b2
--check
lee las rutas dentro del manifiesto. Esas rutas incluyen directorios, por lo que los dos archivos
app.tar siguen siendo distintos. Las rutas relativas se resuelven desde tu
directorio actual, no desde el directorio del manifiesto. Copia toda la estructura de directorios
junto con el manifiesto al verificar un conjunto transferido.
find -print0 y parallel -0 preservan los límites de los nombres
de archivo. El manifiesto en sí usa el
formato de GNU delimitado por saltos de línea con secuencias de escape,
que puede representar saltos de línea y barras invertidas en los nombres de archivo. No dividas sus
registros por espacios en blanco ni añadas b2sum --zero: la salida de sumas de
verificación delimitada por NUL
no es compatible con --check.
Ahora modifica solo el artefacto previsto y repite el paso de verificación:
printf 'changed release\n' >> backups/app.tar &&
b2sum --check --strict --quiet checksums.b2
El comando termina con un estado distinto de cero e informa de una discrepancia en la suma de
verificación de ./backups/app.tar, aunque backups/archive/app.tar siga existiendo.
Un archivo registrado que falte o no se pueda leer también provoca un fallo.
Además, --strict hace que los registros de sumas de verificación con formato
incorrecto provoquen un fallo. Corrige el artefacto o restáuralo a partir de una copia de confianza
antes de volver a verificarlo; regenerar el manifiesto supondría aceptar los bytes modificados.
La verificación comprueba los elementos registrados. No detecta archivos recién añadidos, no comprueba la estructura de los contenedores ni determina quién creó los artefactos. Cuando quieras cambiar la referencia, realiza una nueva ejecución del productor y revísala, en lugar de dar por verificados los archivos adicionales.
Propaga los fallos en CI
Guarda el comando de verificación como verify-backups.sh para que su estado llegue a
quien lo invoca:
#!/usr/bin/env bash
set -euo pipefail
b2sum --check --strict checksums.b2
Ejecútalo desde el directorio que contiene el manifiesto de confianza y la estructura registrada:
bash verify-backups.sh
Una tarea de CI puede usar esa misma invocación después de obtener un manifiesto protegido del repositorio y poner los artefactos a disposición en las rutas registradas. Mantén la generación del manifiesto fuera de la tarea de verificación. Revisa por separado las actualizaciones legítimas de la referencia y protege el acceso de escritura tanto al manifiesto como a los artefactos. Pasar la salida de la verificación a otro comando mediante una tubería sin conservar su estado de salida puede ocultar una discrepancia.
Mide el rendimiento con tu carga de trabajo
El rendimiento depende del tamaño de los archivos, el almacenamiento, la caché, las instrucciones
de la CPU y la implementación. Estos comandos muestran cómo medir el tiempo con el archivo de la
demostración. Reemplaza backups/app.tar por un archivo representativo completo para
obtener mediciones significativas:
time b2sum -- backups/app.tar > /dev/null &&
time sha256sum -- backups/app.tar > /dev/null
Los diminutos archivos de la demostración no permiten establecer una comparación de velocidad útil.
No supongas que BLAKE2 siempre es más rápido que SHA-256 acelerado por hardware. El cálculo de hashes
en paralelo puede generar contención por el acceso al mismo dispositivo de almacenamiento, así que
mide el efecto de distintas cantidades de procesos de trabajo con tu propio conjunto de datos antes
de aumentar --jobs.
Para verificar un único archivo descargado después de moverlo, usa la guía de verificación con b2sum independiente.
