magicciv/tools/sign-mod.sh
2026-05-26 02:21:12 -07:00

64 lines
2.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# sign-mod.sh — produce the base64 ed25519 signature for a native AI-controller
# mod payload, ready to drop into manifest.json#/signature.
#
# Usage:
# tools/sign-mod.sh <binary-path> <private-key-path>
#
# Where:
# <binary-path> Path to controller.so / controller.dll / controller.dylib
# <private-key-path> PEM-encoded ed25519 private key. Generate one with:
# openssl genpkey -algorithm ed25519 -out engine.key
# and publish the matching public key:
# openssl pkey -in engine.key -pubout -out engine.pub
#
# Output: 88-char base64 string (64 raw bytes) on stdout. Paste into the
# mod's manifest.json #/signature field.
#
# Protocol (mirrors mc-mod-host/src/signing.rs):
# 1. SHA-256 the binary bytes.
# 2. Sign the 32-byte digest with the ed25519 private key.
# 3. Base64-encode the 64-byte signature.
#
# The host re-computes the digest and verifies against the engine-release
# public key embedded in ENGINE_PUBKEY (see signing.rs). Mods built
# without access to the matching private key will not load.
#
# TRACKED: the engine release pubkey constant is currently zero-bytes,
# so signatures produced here will NOT verify against the shipped
# engine until the release pipeline (Stage 6) bakes in a real key.
# See docs/modding/abi-decisions.md §"Native sandbox" for the deferral.
set -euo pipefail
if [[ $# -ne 2 ]]; then
echo "usage: $0 <binary-path> <private-key-path>" >&2
exit 64
fi
BIN="$1"
KEY="$2"
if [[ ! -f "$BIN" ]]; then
echo "error: binary not found: $BIN" >&2
exit 66
fi
if [[ ! -f "$KEY" ]]; then
echo "error: private key not found: $KEY" >&2
exit 66
fi
TMP_DIGEST="$(mktemp)"
TMP_SIG="$(mktemp)"
trap 'rm -f "$TMP_DIGEST" "$TMP_SIG"' EXIT
# 1. SHA-256 the binary into raw 32 bytes.
openssl dgst -sha256 -binary "$BIN" > "$TMP_DIGEST"
# 2. Sign the digest with the ed25519 private key. `openssl pkeyutl` with
# an ed25519 key takes the message directly (no -digest flag).
openssl pkeyutl -sign -inkey "$KEY" -rawin -in "$TMP_DIGEST" -out "$TMP_SIG"
# 3. Base64-encode and emit on a single line.
base64 -w 0 < "$TMP_SIG"
echo