diff --git a/scripts/sign-xmrig-release.sh b/scripts/sign-xmrig-release.sh index ae5791d..d8e3aed 100755 --- a/scripts/sign-xmrig-release.sh +++ b/scripts/sign-xmrig-release.sh @@ -3,70 +3,64 @@ # # The wallet verifies a detached ed25519 signature over the EXACT archive bytes against a public # key pinned in src/util/xmrig_updater.h (kXmrigSignaturePublicKeyBase64). For each archive -# .zip this produces .zip.sig containing the base64 ed25519 signature — upload that -# .sig next to the .zip as a release asset. +# .zip this produces .zip.sig holding the base64 of the raw 64-byte ed25519 signature — +# upload that .sig next to the .zip as a release asset. # -# Keys are 32-byte ed25519: the secret key signs (keep OFFLINE), the public key goes in the wallet. +# Uses OpenSSL (>= 1.1.1) only — no Python/PyNaCl needed. OpenSSL's ed25519 is PureEdDSA (RFC 8032), +# the same primitive libsodium's crypto_sign_verify_detached checks, so signatures are compatible +# (verified by the wallet's unit tests + an interop check). # # Usage: -# scripts/sign-xmrig-release.sh keygen [out-prefix] # -> .ed25519.{key,pub.b64} -# scripts/sign-xmrig-release.sh sign ... # -> .sig per file -# scripts/sign-xmrig-release.sh pubkey # print the base64 public key to pin +# scripts/sign-xmrig-release.sh keygen [out-prefix] # -> .ed25519.{key,pub.b64} +# scripts/sign-xmrig-release.sh pubkey # print the base64 public key to pin +# scripts/sign-xmrig-release.sh sign ...# -> .sig per file # -# Requires python3 with PyNaCl (pip install pynacl). PyNaCl uses the same libsodium primitives the -# wallet verifies with, so signatures are guaranteed compatible. +# Keep the secret key (.ed25519.key) OFFLINE. Paste the base64 public key into +# kXmrigSignaturePublicKeyBase64 in src/util/xmrig_updater.h. set -euo pipefail - die() { echo "error: $*" >&2; exit 1; } -command -v python3 >/dev/null || die "python3 not found" -python3 -c 'import nacl.signing' 2>/dev/null || die "PyNaCl missing — run: pip install pynacl" +command -v openssl >/dev/null || die "openssl not found (need >= 1.1.1 with ed25519)" + +# Raw 32-byte ed25519 public key (base64) from a private key file. The DER SubjectPublicKeyInfo for +# ed25519 is a fixed 12-byte prefix + the 32-byte key, so the trailing 32 bytes are the raw key. +pubkey_b64() { openssl pkey -in "$1" -pubout -outform DER | tail -c 32 | openssl base64 -A; } cmd="${1:-}"; shift || true - case "$cmd" in keygen) prefix="${1:-drg-xmrig}" - python3 - "$prefix" <<'PY' -import sys, base64, nacl.signing -prefix = sys.argv[1] -sk = nacl.signing.SigningKey.generate() -open(prefix + ".ed25519.key", "wb").write(bytes(sk)) -import os; os.chmod(prefix + ".ed25519.key", 0o600) -pub_b64 = base64.standard_b64encode(bytes(sk.verify_key)).decode() -open(prefix + ".ed25519.pub.b64", "w").write(pub_b64 + "\n") -print("secret key : %s.ed25519.key (KEEP OFFLINE, mode 600)" % prefix) -print("public key : %s.ed25519.pub.b64" % prefix) -print() -print("Pin this in src/util/xmrig_updater.h (kXmrigSignaturePublicKeyBase64):") -print(" %s" % pub_b64) -PY - ;; - sign) - [ $# -ge 2 ] || die "usage: sign ..." - keyfile="$1"; shift - for f in "$@"; do - [ -f "$f" ] || die "no such file: $f" - python3 - "$keyfile" "$f" <<'PY' -import sys, base64, nacl.signing -keyfile, f = sys.argv[1], sys.argv[2] -sk = nacl.signing.SigningKey(open(keyfile, "rb").read()) -sig = sk.sign(open(f, "rb").read()).signature # 64-byte detached ed25519 signature -open(f + ".sig", "w").write(base64.standard_b64encode(sig).decode() + "\n") -print("signed: %s -> %s.sig" % (f, f)) -PY - done - echo "Upload each .sig as a release asset next to its archive." + [ -e "$prefix.ed25519.key" ] && die "$prefix.ed25519.key already exists — refusing to overwrite" + openssl genpkey -algorithm ed25519 -out "$prefix.ed25519.key" + chmod 600 "$prefix.ed25519.key" + pub="$(pubkey_b64 "$prefix.ed25519.key")" + printf '%s\n' "$pub" > "$prefix.ed25519.pub.b64" + echo "secret key : $prefix.ed25519.key (KEEP OFFLINE, mode 600)" + echo "public key : $prefix.ed25519.pub.b64" + echo + echo "Pin this in src/util/xmrig_updater.h (kXmrigSignaturePublicKeyBase64):" + echo " $pub" ;; pubkey) [ $# -ge 1 ] || die "usage: pubkey " - python3 - "$1" <<'PY' -import sys, base64, nacl.signing -sk = nacl.signing.SigningKey(open(sys.argv[1], "rb").read()) -print(base64.standard_b64encode(bytes(sk.verify_key)).decode()) -PY + pubkey_b64 "$1" + ;; + sign) + [ $# -ge 2 ] || die "usage: sign ..." + key="$1"; shift + [ -f "$key" ] || die "no such key: $key" + for f in "$@"; do + [ -f "$f" ] || die "no such file: $f" + raw="$(mktemp)" + openssl pkeyutl -sign -inkey "$key" -rawin -in "$f" -out "$raw" + openssl base64 -A -in "$raw" > "$f.sig" + printf '\n' >> "$f.sig" + rm -f "$raw" + echo "signed: $f -> $f.sig" + done + echo "Upload each .sig as a release asset next to its archive." ;; *) - die "usage: $0 {keygen [prefix] | sign ... | pubkey }" + die "usage: $0 {keygen [prefix] | pubkey | sign ...}" ;; esac