init: keys repo with keygen, sign, verify scripts and mchusavitin public key

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 10:23:47 +03:00
commit 9ffc57ec1a
7 changed files with 235 additions and 0 deletions

49
scripts/keygen.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/bin/sh
# keygen.sh — generate an Ed25519 keypair for signing release binaries
#
# Usage:
# sh scripts/keygen.sh <developer-name>
#
# Output:
# ~/.keys/<developer-name>.key — private key (KEEP SECRET, never commit)
# developers/<developer-name>.pub — public key (safe to commit here)
#
# Requirements: openssl 3.x
set -e
NAME="$1"
if [ -z "$NAME" ]; then
echo "Usage: sh scripts/keygen.sh <developer-name>" >&2
echo "Example: sh scripts/keygen.sh mchusavitin" >&2
exit 1
fi
PRIVATE_KEY_PATH="$HOME/.keys/${NAME}.key"
PUBLIC_KEY_PATH="$(dirname "$0")/../developers/${NAME}.pub"
if [ -f "$PRIVATE_KEY_PATH" ]; then
echo "Private key already exists at $PRIVATE_KEY_PATH" >&2
echo "Delete it manually if you want to regenerate." >&2
exit 1
fi
mkdir -p "$HOME/.keys"
chmod 700 "$HOME/.keys"
# Generate Ed25519 private key (PEM format)
openssl genpkey -algorithm ed25519 -out "$PRIVATE_KEY_PATH"
chmod 600 "$PRIVATE_KEY_PATH"
# Extract raw 32-byte public key and base64-encode it
openssl pkey -in "$PRIVATE_KEY_PATH" -pubout -outform DER \
| tail -c 32 \
| base64 > "$PUBLIC_KEY_PATH"
echo "Private key: $PRIVATE_KEY_PATH (DO NOT share or commit)"
echo "Public key: $PUBLIC_KEY_PATH (commit this to the keys repo)"
echo ""
echo "Next steps:"
echo " 1. git add developers/${NAME}.pub && git commit -m 'add ${NAME} public key'"
echo " 2. git push"
echo " 3. Rebuild any release binaries to include the new key"

49
scripts/sign-release.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/bin/sh
# sign-release.sh — sign a release binary with your Ed25519 private key
#
# Usage:
# sh scripts/sign-release.sh <developer-name> <binary-path>
#
# Output:
# <binary-path>.sig — raw 64-byte Ed25519 signature
#
# The .sig file must be uploaded alongside the binary to the Gitea release.
#
# Requirements: openssl 3.x
set -e
NAME="$1"
BINARY="$2"
if [ -z "$NAME" ] || [ -z "$BINARY" ]; then
echo "Usage: sh scripts/sign-release.sh <developer-name> <binary-path>" >&2
echo "Example: sh scripts/sign-release.sh mchusavitin dist/bee-audit-linux-amd64" >&2
exit 1
fi
PRIVATE_KEY_PATH="$HOME/.keys/${NAME}.key"
SIG_PATH="${BINARY}.sig"
if [ ! -f "$PRIVATE_KEY_PATH" ]; then
echo "Private key not found: $PRIVATE_KEY_PATH" >&2
echo "Run scripts/keygen.sh $NAME first." >&2
exit 1
fi
if [ ! -f "$BINARY" ]; then
echo "Binary not found: $BINARY" >&2
exit 1
fi
# Sign: produce raw 64-byte Ed25519 signature
openssl pkeyutl -sign \
-inkey "$PRIVATE_KEY_PATH" \
-rawin \
-in "$BINARY" \
-out "$SIG_PATH"
echo "Signed: $BINARY"
echo "Signature: $SIG_PATH"
echo ""
echo "Upload both files to the Gitea release as assets."

75
scripts/verify-signature.sh Executable file
View File

@@ -0,0 +1,75 @@
#!/bin/sh
# verify-signature.sh — verify a release binary signature against any trusted public key
#
# Usage:
# sh scripts/verify-signature.sh <binary-path>
#
# Verifies <binary-path>.sig against all keys in developers/*.pub
# Exits 0 if any key matches, 1 if none match.
#
# Requirements: openssl 3.x, python3 (for base64 decode)
set -e
BINARY="$1"
SIG_PATH="${BINARY}.sig"
KEYS_DIR="$(dirname "$0")/../developers"
if [ -z "$BINARY" ]; then
echo "Usage: sh scripts/verify-signature.sh <binary-path>" >&2
exit 1
fi
if [ ! -f "$BINARY" ]; then
echo "Binary not found: $BINARY" >&2
exit 1
fi
if [ ! -f "$SIG_PATH" ]; then
echo "Signature not found: $SIG_PATH" >&2
exit 1
fi
MATCHED=""
for PUBFILE in "$KEYS_DIR"/*.pub; do
[ -f "$PUBFILE" ] || continue
NAME=$(basename "$PUBFILE" .pub)
# Decode base64 raw public key → DER SubjectPublicKeyInfo wrapper
# Ed25519 DER prefix: 302a300506032b6570032100
RAW_B64=$(cat "$PUBFILE")
PEM_PATH="/tmp/verify-${NAME}.pem"
python3 - "$RAW_B64" "$PEM_PATH" <<'PYEOF'
import sys, base64, binascii
raw = base64.b64decode(sys.argv[1])
prefix = bytes.fromhex("302a300506032b6570032100")
der = prefix + raw
b64 = base64.b64encode(der).decode()
with open(sys.argv[2], "w") as f:
f.write("-----BEGIN PUBLIC KEY-----\n")
for i in range(0, len(b64), 64):
f.write(b64[i:i+64] + "\n")
f.write("-----END PUBLIC KEY-----\n")
PYEOF
if openssl pkeyutl -verify \
-pubin -inkey "$PEM_PATH" \
-rawin \
-in "$BINARY" \
-sigfile "$SIG_PATH" \
2>/dev/null; then
echo "OK: signature verified by key '$NAME'"
MATCHED="$NAME"
rm -f "$PEM_PATH"
break
fi
rm -f "$PEM_PATH"
done
if [ -z "$MATCHED" ]; then
echo "FAIL: signature does not match any trusted key in developers/" >&2
exit 1
fi