aere-node/validator/validator-keys.sh

100 lines
5.5 KiB
Bash

#!/usr/bin/env bash
#
# validator-keys.sh - generate a chain-2800 validator's post-quantum keys ON THIS MACHINE.
#
# A validator of Aere Network holds three keys, and all three are generated by the operator, never by
# the Foundation and never anywhere else:
#
# 1. secp256k1, the NODE key (<data-path>/key). It is also the consensus key: Besu sends consensus
# messages only to peers whose node-key address is in the validator set, so a validator whose
# node key is not its validator key receives no consensus message at all. The node creates this
# key the first time it starts (run-node.sh); this script uses it and does not replace it.
# 2. Falcon-512, the key behind every post-quantum seal (aere.falcon.key).
# 3. SLH-DSA-SHA2-128s, the second scheme of the hybrid anchor certificate
# (aere.pq.hybrid.key.slh-dsa-sha2-128s).
#
# 2 and 3 are generated by PqRegistryV3Tool keygen, the tool inside YOUR build of the published patch
# series (patch 0008): owner-only files, never overwritten, only the public keys printed.
#
# Nothing private is printed, logged or sent. The script checks its own output for that before it ends.
#
# Usage:
# validator/validator-keys.sh --params <admission-params.json> [options]
#
# --params <file> the admission parameters the Foundation sends you (chainId, bindHeight, count,
# index): public, and the index is written into the key files
# --build-dir <dir> the build made by run-node.sh. Default: ./.besu-build next to run-node.sh
# --data-path <dir> the node's data directory (holds the node key). Default: ./aere-data next to run-node.sh
# --keys-dir <dir> where the two post-quantum keys are written (created owner-only).
# Default: $HOME/.aere-validator/keys (outside the repository, on purpose)
# --create-node-key create <data-path>/key with Besu's own KeyPairUtil if it does not exist yet
# (the usual way is to start the node once; it creates the key itself)
# -h | --help
#
set -euo pipefail
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/kit-common.sh"
PARAMS=""; BUILD_DIR="$BUNDLE_DIR/.besu-build"; DATA_PATH="$BUNDLE_DIR/aere-data"; KEYS_DIR="${HOME}/.aere-validator/keys"; CREATE=0
usage() { awk 'NR>=2 && /^#/{sub(/^# ?/,"");print;next} NR>=2{exit}' "${BASH_SOURCE[0]}"; exit 0; }
while [ $# -gt 0 ]; do
case "$1" in
--params) PARAMS="${2:-}"; shift 2 ;;
--build-dir) BUILD_DIR="${2:-}"; shift 2 ;;
--data-path) DATA_PATH="${2:-}"; shift 2 ;;
--keys-dir) KEYS_DIR="${2:-}"; shift 2 ;;
--create-node-key) CREATE=1; shift ;;
-h|--help) usage ;;
*) die "unknown argument: $1 (try --help)" ;;
esac
done
[ -n "$PARAMS" ] && [ -f "$PARAMS" ] || die "--params <admission-params.json> is required (the Foundation sends it)"
say "1/4 The build"
kit_find_lib "$BUILD_DIR"
say "2/4 The admission parameters"
read -r CHAIN BIND COUNT INDEX < <(kit_java params --params "$PARAMS" 2>/dev/null) || die "the admission parameters do not parse (run: java -cp '$LIB/*' $KIT_DIR/AereCandidacy.java params --params $PARAMS)"
[ -n "${INDEX:-}" ] || die "the admission parameters do not parse"
ok "chain $CHAIN, registry epoch bound at block $BIND, $COUNT rows, your row index $INDEX"
say "3/4 The node key (secp256k1, also the consensus key)"
NK="$DATA_PATH/key"
if [ ! -f "$NK" ]; then
[ "$CREATE" = 1 ] || die "$NK does not exist. Start your node once with run-node.sh (it creates the key), stop it, and run this again; or pass --create-node-key"
[ -d "$DATA_PATH" ] || (umask 077; mkdir -p "$DATA_PATH")
(umask 077; kit_java node-key --data-path "$DATA_PATH" > /dev/null 2>&1) || die "the node key could not be created with Besu's KeyPairUtil"
ok "created $NK with Besu's own KeyPairUtil"
fi
need_private_file "$NK"
say "4/4 The post-quantum keys"
FK="$KEYS_DIR/falcon-512.key"; SK="$KEYS_DIR/slh-dsa-sha2-128s.key"
if [ ! -d "$KEYS_DIR" ]; then (umask 077; mkdir -p "$KEYS_DIR"); fi
need_private_dir "$KEYS_DIR"
if [ -f "$FK" ] && [ -f "$SK" ]; then
note "both keys already exist in $KEYS_DIR; they are NOT regenerated (a key is never replaced by this script)"
elif [ -f "$FK" ] || [ -f "$SK" ]; then
die "only one of the two keys exists in $KEYS_DIR; refusing to guess. Move the directory aside and run again"
else
(umask 077; java -Xmx512m -cp "$LIB/*" org.hyperledger.besu.consensus.common.bft.tools.PqRegistryV3Tool keygen \
--index "$INDEX" --out-falcon "$FK" --out-slh "$SK" > "$KEYS_DIR/keygen-public.json" 2> "$KEYS_DIR/keygen.log" < /dev/null) \
|| die "PqRegistryV3Tool keygen failed (see $KEYS_DIR/keygen.log)"
ok "generated by PqRegistryV3Tool keygen in your build"
fi
need_private_file "$FK"; need_private_file "$SK"
IDS_FILE="$(mktemp "$KEYS_DIR/.ids.XXXXXX")"; trap 'rm -f "$IDS_FILE"' EXIT
kit_java ids --node-key-file "$NK" --falcon-key "$FK" --slh-key "$SK" > "$IDS_FILE" 2> "$KEYS_DIR/ids.log" \
|| die "the keys do not form one identity (see $KEYS_DIR/ids.log)"
grep -q "\"index\" : $INDEX\b" "$IDS_FILE" || die "the key files are not for index $INDEX (keys generated for another admission?)"
kit_no_private_in "$FK" "$SK" "$NK" "$IDS_FILE" "$KEYS_DIR/keygen-public.json" "$KEYS_DIR/keygen.log" "$KEYS_DIR/ids.log"
say "Your validator identity (public; nothing private is shown)"
sed 's/^/ /' "$IDS_FILE"
cat <<EOF
The two private key files stay in $KEYS_DIR, owner-only. Back them up OFFLINE together with
$NK: losing them means a new admission; leaking them lets someone sign as your validator.
Next: validator/validator-candidacy.sh --params $PARAMS --enode-host <your public P2P host>
EOF