#!/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 (/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 [options] # # --params the admission parameters the Foundation sends you (chainId, bindHeight, count, # index): public, and the index is written into the key files # --build-dir the build made by run-node.sh. Default: ./.besu-build next to run-node.sh # --data-path the node's data directory (holds the node key). Default: ./aere-data next to run-node.sh # --keys-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 /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 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