#!/usr/bin/env bash # depo-sign.sh — sign a package manifest with an ed25519 key (per manifest-spec v1.0). # Writes, next to the manifest: # .sha256 — hex hash of manifest.json # .sig — base64 ed25519 signature over the manifest bytes # # Usage: # depo-sign.sh [--key ] [--out ] # --key ed25519 private key (PEM). Default: $DEPO_SIGNING_KEY # --out where artifacts land. Default: package dir (side-by-side with manifest) set -euo pipefail usage() { echo "usage: $0 [--key ] [--out ]"; exit 1; } PKG_DIR="${1:?missing package dir}"; shift KEY="${DEPO_SIGNING_KEY:-}" OUT="" while [ $# -gt 0 ]; do case "$1" in --key) KEY="${2:?}"; shift 2 ;; --out) OUT="${2:?}"; shift 2 ;; *) usage ;; esac done MANIFEST="$PKG_DIR/manifest.json" [ -f "$MANIFEST" ] || { echo "depo-sign: no manifest.json in $PKG_DIR" >&2; exit 1; } [ -n "$KEY" ] && [ -f "$KEY" ] || { echo "depo-sign: no ed25519 key (set --key or DEPO_SIGNING_KEY)" >&2; exit 1; } OUT="${OUT:-$PKG_DIR}" mkdir -p "$OUT" SHA="$(sha256sum "$MANIFEST" | cut -d' ' -f1)" printf '%s\n' "$SHA" > "$OUT/manifest.json.sha256" python3 - "$KEY" "$MANIFEST" "$OUT/manifest.json.sig" <<'PY' import base64, sys from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey key_path, manifest_path, out_path = sys.argv[1], sys.argv[2], sys.argv[3] data = open(key_path, "rb").read() try: key = serialization.load_pem_private_key(data, password=None) except ValueError: key = Ed25519PrivateKey.from_private_bytes(data) # raw 32-byte fallback if not isinstance(key, Ed25519PrivateKey): raise SystemExit("depo-sign: key is not an ed25519 key") manifest = open(manifest_path, "rb").read() sig = key.sign(manifest) open(out_path, "wb").write(base64.b64encode(sig)) PY echo "depo-sign: signed $MANIFEST" echo " sha256 $OUT/manifest.json.sha256" echo " sig $OUT/manifest.json.sig"