#!/usr/bin/env sh # CheckPQC CLI installer (POSIX sh; works on macOS/Linux/BSD). # # Usage: # curl -fsSL https://checkpqc.com/install.sh | sh # # Pin a version: # curl -fsSL https://checkpqc.com/install.sh | CHECKPQC_VERSION=0.2.8 sh # # Force reinstall: # curl -fsSL https://checkpqc.com/install.sh | CHECKPQC_FORCE=1 sh # # This script does NOT bundle Node or OpenSSL. For a self-contained option: # docker run --rm ghcr.io/aegyrix/check-pqc:latest example.com set -eu VERSION="${CHECKPQC_VERSION:-}" FORCE="${CHECKPQC_FORCE:-0}" # --- color helpers (ANSI) ------------------------------------------------- if [ -t 1 ] && command -v tput >/dev/null 2>&1 && [ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]; then CYAN="$(tput setaf 6)"; GREEN="$(tput setaf 2)" YELLOW="$(tput setaf 3)"; RED="$(tput setaf 1)" DIM="$(tput dim)"; BOLD="$(tput bold)"; RESET="$(tput sgr0)" else CYAN=""; GREEN=""; YELLOW=""; RED=""; DIM=""; BOLD=""; RESET="" fi step() { printf '%s==>%s %s\n' "$CYAN" "$RESET" "$1"; } ok() { printf ' %sāœ“%s %s\n' "$GREEN" "$RESET" "$1"; } warn() { printf ' %s!%s %s\n' "$YELLOW" "$RESET" "$1"; } die() { printf ' %sāœ—%s %s\n' "$RED" "$RESET" "$1" >&2; exit 1; } has() { command -v "$1" >/dev/null 2>&1; } ask_yes_no() { prompt="$1" if [ ! -r /dev/tty ]; then return 1 fi printf '%s [y/N] ' "$prompt" >/dev/tty read answer = 18)' if ! has node; then warn 'Node.js is not installed. check-pqc needs Node.js 18+ for the local CLI path.' if ask_yes_no 'Install Node.js now?'; then install_node || die 'No supported package manager found. Install Node.js 18+ and rerun this script.' else die 'Install Node.js 18+ and rerun this script.' fi fi NODE_VERSION="$(node --version 2>/dev/null | sed 's/^v//')" NODE_MAJOR="${NODE_VERSION%%.*}" case "$NODE_MAJOR" in ''|*[!0-9]*) die "could not parse node version: $NODE_VERSION" ;; esac if [ "$NODE_MAJOR" -lt 18 ]; then warn "Node.js $NODE_VERSION found; check-pqc requires Node 18+." if ask_yes_no 'Upgrade/install a newer Node.js now?'; then install_node || die 'No supported package manager found. Upgrade Node.js to 18+ and rerun this script.' NODE_VERSION="$(node --version 2>/dev/null | sed 's/^v//')" NODE_MAJOR="${NODE_VERSION%%.*}" [ "$NODE_MAJOR" -ge 18 ] || die "Node.js $NODE_VERSION found after install; still need Node 18+." else die 'Upgrade Node.js to 18+ and rerun this script.' fi fi ok "Node.js $NODE_VERSION" if ! has npm; then warn 'npm is not on PATH (Node install incomplete?).' if ask_yes_no 'Install npm now?'; then install_node || die 'No supported package manager found. Install npm and rerun this script.' else die 'Install npm and rerun this script.' fi fi ok "npm $(npm --version)" # --- pre-flight: OpenSSL (informational) --------------------------------- step 'Checking OpenSSL (3.5+ with ML-KEM, optional but recommended)' if has openssl; then OPENSSL_LINE="$(openssl version 2>/dev/null | tr -s ' ')" ok "openssl: $OPENSSL_LINE" if openssl list -tls-groups 2>/dev/null | grep -qi 'mlkem'; then ok 'ML-KEM TLS groups available (full live-probe support)' else warn 'OpenSSL present but no ML-KEM groups detected.' warn 'Live probes work for SERVER_ONLY/CLIENT_ONLY verdicts.' if ask_yes_no 'Install or upgrade OpenSSL now for full local PQC proofs?'; then install_openssl || warn 'No supported package manager found. Install OpenSSL 3.5+ manually.' else warn 'For full PQC capability later, install OpenSSL 3.5+ or use:' warn ' docker run --rm ghcr.io/aegyrix/check-pqc:offline ' fi fi else warn 'OpenSSL not found on PATH. Live probes need OpenSSL 3.5+.' warn 'Offline checks (--check-offline) will still work.' if ask_yes_no 'Install OpenSSL now for full local PQC proofs?'; then install_openssl || warn 'No supported package manager found. Install OpenSSL 3.5+ manually.' fi fi # --- existing install? --------------------------------------------------- if has check-pqc && [ "$FORCE" != "1" ]; then EXISTING="$(check-pqc --version 2>/dev/null || echo unknown)" step "Existing install detected: $EXISTING" if [ -n "$VERSION" ] && [ "${EXISTING#*$VERSION}" = "$EXISTING" ]; then step "Pinned version \"$VERSION\" requested; reinstalling" else warn 'Re-run with CHECKPQC_FORCE=1 to reinstall, or upgrade with:' warn ' npm update -g @aegyrix/check-pqc' printf '\n %sAlready installed. Try:%s\n' "$BOLD" "$RESET" printf ' check-pqc google.com\n' printf ' check-pqc --check-offline\n\n' exit 0 fi fi # --- install -------------------------------------------------------------- PKG="@aegyrix/check-pqc@${VERSION:-latest}" step "Installing $PKG globally via npm" # Some shared installs need sudo; detect whether the current npm prefix is # writable, and only escalate if necessary. Honors NPM_CONFIG_PREFIX/NVM. NPM_PREFIX="$(npm config get prefix 2>/dev/null || echo /usr/local)" NPM_BIN="$NPM_PREFIX/bin" NEEDS_SUDO=0 if [ ! -w "$NPM_PREFIX" ] && [ ! -w "$NPM_BIN" ]; then if has sudo; then NEEDS_SUDO=1 warn "npm prefix $NPM_PREFIX not writable; using sudo for install" else die "npm prefix $NPM_PREFIX not writable and sudo unavailable. Use a Node version manager (nvm, fnm, asdf)." fi fi set +e if [ "$NEEDS_SUDO" = "1" ]; then sudo npm install -g "$PKG" else npm install -g "$PKG" fi NPM_RC=$? set -e [ $NPM_RC -eq 0 ] || die "npm install failed (exit $NPM_RC)" ok 'Installed' # --- verify --------------------------------------------------------------- step 'Verifying install' # Refresh PATH lookup (some shells cache). hash -r 2>/dev/null || true if ! has check-pqc; then cat >&2 </dev/null | tr -d '[:space:]')" # Confirm offline capability runs cleanly. Exit 0 (full) and 2 (partial) # are both healthy installs; only treat hard failures (1, 3) as warnings. set +e check-pqc --check-offline >/dev/null 2>&1 RC=$? set -e if [ $RC -ne 0 ] && [ $RC -ne 2 ]; then warn "check-pqc --check-offline exited $RC; install OpenSSL 3.5+ for full capability." fi # --- next steps ----------------------------------------------------------- printf '\n %sāœ“ Done.%s\n\n' "$GREEN$BOLD" "$RESET" printf ' %sTry a probe:%s\n' "$BOLD" "$RESET" printf ' check-pqc google.com\n' printf ' check-pqc --json checkpqc.app\n' printf ' check-pqc --check-offline\n\n' printf ' %sDocs:%s https://checkpqc.com/cli\n' "$DIM" "$RESET" printf ' %sSource:%s https://github.com/aegyrix/checkpqc.app\n\n' "$DIM" "$RESET"