#!/usr/bin/env bash # dm-sign.sh — produce a signed DM for the fleet DM system. # # Signs a message with an SSH key (namespace "dm", Ed25519) and prints the # signed wire format that `dm.py verify-sig` checks: # # [from:] [id:] # # # # -----BEGIN SSH SIGNATURE----- # ... # -----END SSH SIGNATURE----- # # The signed payload is exactly "[from:X] [id:Y]\n\n" (no trailing # newline) — verify-sig reconstructs it by stripping everything from the # signature block onward, so the two must match byte-for-byte. # # Usage: # dm-sign.sh --from [--key ] [--id ] # # Defaults: --key ~/.ssh/id_frontdoor, --id = 8 random hex chars. # The private key is only ever read locally; it is never moved or copied. # Pipe the output straight into `dm.py send --raw` (never truncate it). # # Example: # dm.py send --agent opm --target main --raw \ # "$(dm-sign.sh --from operator-main 'hello from the operator')" set -euo pipefail FROM="" KEY="$HOME/.ssh/id_frontdoor" ID="$(head -c4 /dev/urandom | od -An -tx1 | tr -d ' \n')" usage() { sed -n '2,/^set -euo/p' "$0" | sed 's/^# \?//' } while [[ $# -gt 0 ]]; do case "$1" in --from) FROM="${2:?--from needs a value}"; shift 2 ;; --key) KEY="${2:?--key needs a value}"; shift 2 ;; --id) ID="${2:?--id needs a value}"; shift 2 ;; -h|--help) usage; exit 0 ;; --) shift; break ;; -*) echo "error: unknown option: $1" >&2; exit 1 ;; *) break ;; esac done if [[ $# -eq 0 ]]; then echo "error: no message given" >&2 echo "usage: dm-sign.sh --from [--key ] [--id ] " >&2 exit 1 fi MESSAGE="$*" [[ -n "$FROM" ]] || { echo "error: --from is required" >&2; exit 1; } [[ -f "$KEY" ]] || { echo "error: private key not found: $KEY" >&2; exit 1; } TD="$(mktemp -d)" trap 'rm -rf "$TD"' EXIT PAYLOAD="$TD/payload" # Payload: header, blank line, body — NO trailing newline (verify-sig strips). printf '[from:%s] [id:%s]\n\n%s' "$FROM" "$ID" "$MESSAGE" > "$PAYLOAD" # Never reuse a stale signature: a leftover .sig from an earlier run would # silently sign the wrong payload (burned 20 minutes on the board, 2026-10-03). rm -f "$PAYLOAD.sig" ssh-keygen -Y sign -f "$KEY" -n dm "$PAYLOAD" >/dev/null printf '[from:%s] [id:%s]\n\n%s\n\n' "$FROM" "$ID" "$MESSAGE" cat "$PAYLOAD.sig"