Files
JGoyd/scripts/anchor.sh
T
2026-05-18 22:58:05 -07:00

65 lines
2.1 KiB
Bash

#!/usr/bin/env bash
# anchor.sh — Hash, PGP-sign, and OpenTimestamps-anchor a single artifact.
#
# Usage: ./anchor.sh path/to/artifact.eml
# Effect: Produces <artifact>.sha256, <artifact>.asc, <artifact>.ots in the same directory.
#
# Requirements:
# gpg (with the canonical signing key already imported and the fingerprint
# configured below or in env var GOYD_PGP_FPR)
# sha256sum (coreutils)
# ots (pip install opentimestamps-client)
#
# Resilience notes:
# - We sign the hash FILE, not the artifact directly. This is so a verifier
# can cheaply check "this artifact is the one I anchored" without re-reading
# a multi-MB file.
# - We OTS-anchor the hash FILE for the same reason: small file, fast Bitcoin
# attestation, no need to push the artifact body anywhere.
set -euo pipefail
if [[ $# -ne 1 ]]; then
echo "usage: $0 <artifact-path>" >&2
exit 64
fi
ART="$1"
if [[ ! -f "$ART" ]]; then
echo "not a file: $ART" >&2
exit 66
fi
# CHOOSE ONE canonical signing key. The user currently has two fingerprints in
# circulation; reconcile before using this script in production.
FPR="${GOYD_PGP_FPR:-4A041F506D894F5EE391743864878B56A2EB2D11}"
DIR="$(dirname "$ART")"
BASE="$(basename "$ART")"
HASH_FILE="${ART}.sha256"
SIG_FILE="${ART}.asc"
OTS_FILE="${HASH_FILE}.ots"
# 1. Hash
( cd "$DIR" && sha256sum "$BASE" ) > "$HASH_FILE"
echo "wrote $HASH_FILE"
# 2. PGP-sign the artifact (detached, armored)
gpg --local-user "$FPR" --armor --detach-sign --output "$SIG_FILE" "$ART"
echo "wrote $SIG_FILE"
# 3. PGP-sign the hash file too (so a verifier can cheaply confirm the binding)
gpg --local-user "$FPR" --armor --detach-sign --output "${HASH_FILE}.asc" "$HASH_FILE"
echo "wrote ${HASH_FILE}.asc"
# 4. OpenTimestamps-anchor the hash file
ots stamp "$HASH_FILE"
echo "wrote $OTS_FILE (pending Bitcoin confirmation, run 'ots upgrade' later)"
echo
echo "Verification commands a third party will run:"
echo " sha256sum -c $HASH_FILE"
echo " gpg --verify $SIG_FILE $ART"
echo " gpg --verify ${HASH_FILE}.asc $HASH_FILE"
echo " ots verify $OTS_FILE"