Verificar manifestos de artefatos com b2sum e GNU Parallel
Use o GNU b2sum para registrar um conjunto de artefatos concluídos e depois
verifique esse conjunto sem gerar novamente os valores esperados. Este guia calcula hashes de um
pequeno diretório de backup em paralelo, substitui o manifesto somente após o cálculo de todos os
hashes ter sucesso e propaga falhas de verificação para um shell ou uma tarefa de CI.
Um resumo criptográfico, por si só, não comprova quem criou um arquivo: obtenha a soma de verificação esperada por um canal confiável, como uma versão autenticada ou um manifesto assinado, em vez de baixar tanto o arquivo quanto a soma de uma fonte não confiável.
Escolher o formato correspondente de soma de verificação
O GNU b2sum
usa BLAKE2b-512 por padrão, representado por 128 caracteres hexadecimais. Use o mesmo algoritmo e
comprimento de resumo criptográfico dos valores esperados. BLAKE2s e SHA-256 são formatos diferentes;
se quem publica fornecer SHA-256, verifique com sha256sum em vez de criar uma
referência BLAKE2 a partir do arquivo baixado.
Esta demonstração cria uma referência local a partir de arquivos conhecidos. Em um fluxo de publicação de versões, gere o manifesto no lado confiável que produz os artefatos, depois que eles estiverem concluídos, e proteja sua origem e seu conteúdo. Quem puder substituir tanto os artefatos quanto os valores esperados poderá fazer a verificação passar.
Verificar os pré-requisitos no Linux
Use Linux com Bash, GNU coreutils, GNU findutils, GNU Parallel e Python 3. No Debian ou Ubuntu,
os pacotes correspondentes são bash, coreutils,
findutils, parallel e python3.
O GNU Parallel requer uma instalação separada; outro comando chamado
parallel não o substitui.
Verifique a disponibilidade antes de criar o diretório da demonstração:
bash --version && b2sum --version && find --version && parallel --version && python3 --version
O exemplo foi testado com Bash 5.3.15, coreutils 9.11, findutils 4.11.0, GNU Parallel 20240222 e Python 3.14.7. O Python apenas cria os arquivos da demonstração e não requer pacotes de terceiros. Este é um fluxo de trabalho local no Linux, não um procedimento para macOS ou Windows.
Criar um pequeno conjunto de artefatos
Comece em um diretório sob seu controle. Este comando entra em um novo diretório e se recusa a reutilizar um que já exista:
mkdir -- integrity-demo && cd -- integrity-demo
Mantenha os demais arquivos e comandos em integrity-demo.
Salve o conteúdo a seguir 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)
Execute uma vez:
python3 -I make-fixture.py
Esses seis arquivos pequenos abrangem conteúdo vazio e binário, nomes-base duplicados, espaços,
Unicode e uma quebra de linha em um nome de arquivo. São bytes de exemplo com o sufixo
.tar, não contêineres de arquivamento tar reais.
O gerador recusa um diretório backups existente. Se a preparação for
interrompida, inspecione o diretório parcial e inicie uma nova demonstração em um diretório ainda
não utilizado; executar o gerador novamente não reparará nem sobrescreverá os arquivos anteriores.
Gerar um manifesto completo
Salve este conteúdo como hash-backups.sh. Execute-o como um script Bash salvo,
em vez de colá-lo no 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
Execute o produtor:
bash hash-backups.sh backups
Ele seleciona recursivamente arquivos regulares com o sufixo .tar
em letras minúsculas, sem seguir entradas de links simbólicos. O GNU Parallel executa até quatro
tarefas de cálculo de hash, agrupa suas saídas e mantém a ordem de entrada já ordenada. Sua
opção --plain ignora perfis pessoais e
configurações de PARALLEL, enquanto --halt now,fail=1
interrompe a execução se um cálculo de hash falhar. Uma seleção vazia, uma falha ao percorrer o
diretório ou uma falha no cálculo de hash encerra o processo com status diferente de zero antes de
substituir checksums.b2.
O diretório temporário fica ao lado do destino, de modo que o mv
final publica o manifesto concluído ao renomeá-lo no mesmo sistema de arquivos. Uma nova execução
bem-sucedida substitui o manifesto anterior; falhas o preservam e removem os arquivos temporários.
Execute um produtor por vez e mantenha o diretório de artefatos inalterado enquanto percorre os
arquivos, calcula hashes ou verifica o conjunto. Isso não é um snapshot do sistema de arquivos.
Verificar os arquivos registrados
Execute o consumidor no mesmo diretório integrity-demo, mantendo
checksums.b2 inalterado:
b2sum --check --strict --quiet checksums.b2 && printf 'All recorded files match checksums.b2\n'
All recorded files match checksums.b2
--check
lê os caminhos contidos no manifesto. Esses caminhos incluem diretórios, de modo que os dois
arquivos app.tar permanecem distintos. Caminhos relativos são resolvidos
a partir do diretório atual, não do diretório do manifesto. Copie toda a estrutura de diretórios
junto com o manifesto ao verificar um conjunto transferido.
find -print0 e parallel -0 preservam os limites dos nomes
de arquivo. O próprio manifesto usa o
formato do GNU delimitado por quebras de linha com caracteres de escape,
que pode representar quebras de linha e barras invertidas em nomes de arquivo. Não separe seus
registros por espaços em branco nem adicione b2sum --zero: a saída de somas
de verificação delimitada por NUL
não é compatível com --check.
Agora altere somente o artefato pretendido e repita a etapa de verificação:
printf 'changed release\n' >> backups/app.tar &&
b2sum --check --strict --quiet checksums.b2
O comando termina com status diferente de zero e informa uma divergência na soma de verificação de
./backups/app.tar, embora backups/archive/app.tar ainda exista.
Um arquivo registrado ausente ou ilegível também causa falha.
--strict também faz a verificação falhar quando há registros de somas de
verificação malformados. Corrija o artefato ou restaure-o a partir de uma cópia confiável antes de
verificar novamente; gerar o manifesto de novo faria com que os bytes alterados fossem aceitos.
A verificação confere os arquivos registrados. Ela não detecta arquivos recém-adicionados, não verifica a estrutura de contêineres de arquivamento nem comprova quem criou os artefatos. Faça uma nova execução revisada do produtor quando pretender alterar a referência, em vez de tratar arquivos adicionais como já verificados.
Propagar falhas no CI
Salve o comando de verificação como verify-backups.sh para que seu status seja
repassado a quem o chamou:
#!/usr/bin/env bash
set -euo pipefail
b2sum --check --strict checksums.b2
Execute-o no diretório que contém o manifesto confiável e a estrutura de diretórios registrada nele:
bash verify-backups.sh
Uma tarefa de CI pode usar a mesma chamada após fazer checkout de um manifesto protegido e disponibilizar os artefatos nos caminhos registrados. Mantenha a geração do manifesto fora da tarefa de verificação. Revise separadamente as atualizações legítimas da referência e proteja o acesso de escrita tanto ao manifesto quanto aos artefatos. Encaminhar a saída da verificação para outro comando por um pipe sem preservar seu status de saída pode ocultar uma divergência.
Medir o desempenho com sua carga de trabalho
O desempenho depende do tamanho dos arquivos, do armazenamento, do cache, das instruções da CPU e
da implementação. Estes comandos mostram como medir o tempo de processamento do arquivo da
demonstração. Substitua backups/app.tar por um arquivo representativo já concluído
para obter medições relevantes:
time b2sum -- backups/app.tar > /dev/null &&
time sha256sum -- backups/app.tar > /dev/null
Os arquivos minúsculos da demonstração não permitem uma comparação útil de velocidade. Não presuma
que BLAKE2 seja sempre mais rápido que SHA-256 com aceleração de hardware. O cálculo de hashes em
paralelo pode gerar disputa pelo mesmo dispositivo de armazenamento, então avalie diferentes
quantidades de unidades de execução com seu próprio conjunto de dados antes de aumentar
--jobs.
Para verificar um único arquivo baixado depois de movê-lo, use o guia específico de verificação com b2sum.
