#!/usr/bin/env bash
# Check a ParetoStack download BEFORE you install it: the signature of the release's SHA256SUMS, then the package's own SHA-256. Needs openssl (present on Linux and macOS).
#   ./verify-download.sh paretostack-linux-0.3.6.tar.gz                       (SHA256SUMS, SHA256SUMS.sig and release-signing-key.pem in the same folder)
#   ./verify-download.sh PACKAGE SHA256SUMS SHA256SUMS.sig release-signing-key.pem
# Compare the key fingerprint it prints with the one at https://hpc-labs.ai/release-signing-key.txt (and in the documentation): it is the one thing you cannot check by computer.
set -euo pipefail
PKG="${1:?usage: verify-download.sh PACKAGE [SHA256SUMS [SHA256SUMS.sig [release-signing-key.pem]]]}"
DIR="$(cd "$(dirname "$PKG")" && pwd)"
SUMS="${2:-$DIR/SHA256SUMS}"; SIG="${3:-$SUMS.sig}"; KEY="${4:-$DIR/release-signing-key.pem}"
for f in "$PKG" "$SUMS" "$SIG" "$KEY"; do [ -f "$f" ] || { echo "missing: $f" >&2; exit 2; }; done
command -v openssl >/dev/null 2>&1 || { echo "openssl is needed to check the signature" >&2; exit 2; }
FP="$(openssl pkey -pubin -in "$KEY" -outform DER | openssl dgst -sha256 -hex | awk '{print toupper($NF)}' | sed 's/../&:/g; s/:$//')"
echo "public key fingerprint: $FP"
if openssl dgst -sha256 -verify "$KEY" -signature "$SIG" "$SUMS" >/dev/null 2>&1; then echo "OK   signature of $(basename "$SUMS") is valid for that key"; else echo "FAIL the signature of $(basename "$SUMS") is NOT valid: do not use this download" >&2; exit 1; fi
NAME="$(basename "$PKG")"
WANT="$(awk -v n="$NAME" '{f=$2; sub(/^.*\//, "", f); if (f == n) print tolower($1)}' "$SUMS" | head -1)"
[ -n "$WANT" ] || { echo "FAIL $NAME is not listed in $(basename "$SUMS"): this is not a file of that release" >&2; exit 1; }
if command -v sha256sum >/dev/null 2>&1; then GOT="$(sha256sum "$PKG" | awk '{print $1}')"; else GOT="$(shasum -a 256 "$PKG" | awk '{print $1}')"; fi
if [ "$GOT" = "$WANT" ]; then echo "OK   $NAME matches the signed list: safe to install"; else echo "FAIL $NAME has sha256 ${GOT:0:16}... but the signed list says ${WANT:0:16}...: the file is damaged or not the release" >&2; exit 1; fi
