100 lines
5.5 KiB
Bash
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
|