From b0ed2ce585d2a6fd7c6d8d4db7422734aedccb58 Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Wed, 12 Aug 2026 11:58:03 -0300 Subject: site: document public deployment contract --- docs/release-verification.md | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'docs/release-verification.md') diff --git a/docs/release-verification.md b/docs/release-verification.md index 32de74f..408bab9 100644 --- a/docs/release-verification.md +++ b/docs/release-verification.md @@ -34,6 +34,16 @@ From a shell with `curl` or `wget`, `sha256sum` and `gpg`: scripts/verify-release.sh latest ``` +The public release host should expose latest-file aliases for convenience: + +```text +https://releases.bitflash.network/SHA256SUMS +https://releases.bitflash.network/SHA256SUMS.asc +``` + +Those aliases must point at the current versioned directory. They do not replace +signature verification; they only make the common manual path shorter. + For a specific release: ```bash -- cgit v1.2.3 From 44fbf6895bd3acd11f552514e746a2e3876cad2d Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Thu, 13 Aug 2026 14:29:14 -0300 Subject: release: package Windows builds with managed Tor --- Makefile | 6 +- README.md | 13 ++++ docs/release-verification.md | 6 ++ docs/tor.md | 16 +++++ scripts/make-release-checksums.sh | 2 + scripts/package-windows-tor.sh | 132 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100755 scripts/package-windows-tor.sh (limited to 'docs/release-verification.md') diff --git a/Makefile b/Makefile index b4d0cf7..d1277a4 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # # make linux build Bitflash-*-x86_64.AppImage # make windows build Bitflash-*-windows.zip (from MSYS2 UCRT64) +# make windows-tor build Bitflash-*-windows-with-tor.zip # make tests build and run standalone unit tests # make checksums create SHA256SUMS for release assets # make verify-release TAG=v1.2.13 @@ -180,6 +181,9 @@ windows: deps-windows @zip -r Bitflash-$(VERSION)-windows.zip Bitflash-$(VERSION)-windows/ @echo "Built: Bitflash-$(VERSION)-windows.zip" +windows-tor: windows + ./scripts/package-windows-tor.sh + # ---- Clean ---------------------------------------------------------------- clean: @@ -206,6 +210,6 @@ sign-checksums: verify-release: ./scripts/verify-release.sh $(if $(TAG),$(TAG),latest) -.PHONY: linux windows clean appimage \ +.PHONY: linux windows windows-tor clean appimage \ tests fuzz-net-message-smoke fuzz-script-smoke checksums sign-checksums verify-release \ deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx diff --git a/README.md b/README.md index a7ce2b2..c30f171 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ configuration — it connects automatically and starts syncing. **Linux:** make the `.AppImage` executable and run it. **Windows:** extract the `-windows.zip` and run `Bitflash.exe`. +If you want managed Tor without a separate Tor install, use the +`-windows-with-tor.zip` package and start Bitflash with `-managedtor`. Every release ships a `SHA256SUMS` covering the assets. Verifying takes a second and is worth doing: @@ -452,6 +454,17 @@ make windows ``` Installs deps via pacman, produces `Bitflash-*-windows.zip`. +To build the Windows package that also carries the Tor Expert Bundle: + +```bash +make windows-tor +``` + +That produces `Bitflash-*-windows-with-tor.zip`. The release script downloads +the Tor Expert Bundle from the official Tor archive, verifies its pinned SHA256, +and places `tor/tor.exe` beside `Bitflash.exe` so `-managedtor` works without a +separate Tor install. + --- ## At a glance diff --git a/docs/release-verification.md b/docs/release-verification.md index 408bab9..04d18a3 100644 --- a/docs/release-verification.md +++ b/docs/release-verification.md @@ -81,6 +81,12 @@ Publish, alongside the assets, `SHA256SUMS` and `SHA256SUMS.asc`, and update is ever rotated, announce the new fingerprint clearly and update the embedded key in `verify-release.sh`. +For Windows releases with managed Tor built in, run `make windows-tor`. It +creates `Bitflash-*-windows-with-tor.zip` by downloading the Tor Expert Bundle, +checking the pinned SHA256 in `scripts/package-windows-tor.sh`, and placing +`tor/tor.exe` next to `Bitflash.exe`. Include that zip in `SHA256SUMS` like any +other release asset. + ## Why this matters `SHA256SUMS` alone protects against a broken download, but not against someone diff --git a/docs/tor.md b/docs/tor.md index 1c0f589..be6a145 100644 --- a/docs/tor.md +++ b/docs/tor.md @@ -53,6 +53,22 @@ Without a value, Bitflash looks for Tor in this order: 2. `tor.exe` or `tor` beside the Bitflash binary; 3. `tor.exe` or `tor` on `PATH`. +Windows releases can also be built as `Bitflash-*-windows-with-tor.zip`. That +package includes the official Tor Expert Bundle under `tor/`, so the first path +above exists immediately after extraction and `bitflash -managedtor` needs no +separate Tor install. + +The bundled-Tor package is created by: + +```bash +make windows-tor +``` + +The packaging script verifies a pinned SHA256 for the downloaded Tor Expert +Bundle before copying it into the release directory. The Tor binary is bundled; +the runtime data directory, hidden-service key, and control cookie are still +created under the user's Bitflash data directory. + To point at a specific Tor executable: ```bash diff --git a/scripts/make-release-checksums.sh b/scripts/make-release-checksums.sh index 5b29e2d..9c4f45a 100755 --- a/scripts/make-release-checksums.sh +++ b/scripts/make-release-checksums.sh @@ -10,6 +10,7 @@ Usage: scripts/make-release-checksums.sh [--sign] [--local-user KEYID] Creates SHA256SUMS for release assets in the current directory: Bitflash-*-windows.zip + Bitflash-*-windows-with-tor.zip Bitflash-*-x86_64.AppImage bitflash-node-*-x86_64 @@ -44,6 +45,7 @@ fi assets=() for pattern in \ "Bitflash-*-windows.zip" \ + "Bitflash-*-windows-with-tor.zip" \ "Bitflash-*-x86_64.AppImage" \ "bitflash-node-*-x86_64" do diff --git a/scripts/package-windows-tor.sh b/scripts/package-windows-tor.sh new file mode 100755 index 0000000..084fd1a --- /dev/null +++ b/scripts/package-windows-tor.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VERSION="${VERSION:-$(sed -n 's/^VERSION[[:space:]]*:= *//p' "$ROOT/Makefile" | head -1)}" + +TOR_VERSION="${TOR_VERSION:-15.0.19}" +TOR_ARCHIVE_NAME="tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz" +TOR_URL="${TOR_URL:-https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/${TOR_ARCHIVE_NAME}}" +TOR_SHA256="${TOR_SHA256:-6AC067402C7B4A3DC37887ED3754B3914B67FDC220C966190683E9CCF91ABF0F}" + +BUNDLE_DIR="${BUNDLE_DIR:-$ROOT/Bitflash-${VERSION}-windows}" +OUT_ZIP="${OUT_ZIP:-$ROOT/Bitflash-${VERSION}-windows-with-tor.zip}" +CACHE_DIR="${CACHE_DIR:-$ROOT/.cache}" +ARCHIVE="${TOR_ARCHIVE:-$CACHE_DIR/$TOR_ARCHIVE_NAME}" + +usage() { + cat </dev/null 2>&1 || { + echo "missing required command: $1" >&2 + exit 1 + } +} + +need sha256sum +need tar +need zip + +if [ ! -d "$BUNDLE_DIR" ]; then + echo "missing Windows release directory: $BUNDLE_DIR" >&2 + echo "run 'make windows' first, or set BUNDLE_DIR" >&2 + exit 1 +fi +if [ ! -f "$BUNDLE_DIR/Bitflash.exe" ]; then + echo "missing Bitflash.exe in $BUNDLE_DIR" >&2 + exit 1 +fi +BUNDLE_PARENT="$(cd "$(dirname "$BUNDLE_DIR")" && pwd)" +BUNDLE_NAME="$(basename "$BUNDLE_DIR")" +OUT_PARENT="$(mkdir -p "$(dirname "$OUT_ZIP")" && cd "$(dirname "$OUT_ZIP")" && pwd)" +OUT_NAME="$(basename "$OUT_ZIP")" +OUT_ZIP_ABS="$OUT_PARENT/$OUT_NAME" + +mkdir -p "$CACHE_DIR" +if [ ! -f "$ARCHIVE" ]; then + if command -v curl >/dev/null 2>&1; then + curl -L --fail --output "$ARCHIVE" "$TOR_URL" + elif command -v wget >/dev/null 2>&1; then + wget -O "$ARCHIVE" "$TOR_URL" + else + echo "missing required command: curl or wget" >&2 + exit 1 + fi +fi + +got="$(sha256sum "$ARCHIVE" | awk '{print tolower($1)}')" +want="$(printf '%s' "$TOR_SHA256" | tr 'A-F' 'a-f')" +if [ "$got" != "$want" ]; then + echo "Tor archive SHA256 mismatch" >&2 + echo " expected: $want" >&2 + echo " got: $got" >&2 + exit 1 +fi + +tmp="$(mktemp -d "${TMPDIR:-/tmp}/bitflash-tor-package.XXXXXX")" +trap 'rm -rf "$tmp"' EXIT + +mkdir -p "$tmp/extract" +tar -xzf "$ARCHIVE" -C "$tmp/extract" + +if [ ! -f "$tmp/extract/tor/tor.exe" ]; then + echo "Tor archive did not contain tor/tor.exe" >&2 + exit 1 +fi + +rm -rf "$BUNDLE_DIR/tor" +mkdir -p "$BUNDLE_DIR/tor" +cp -R "$tmp/extract/tor/." "$BUNDLE_DIR/tor/" +if [ -d "$tmp/extract/docs" ]; then + mkdir -p "$BUNDLE_DIR/tor/docs" + cp -R "$tmp/extract/docs/." "$BUNDLE_DIR/tor/docs/" +fi +if [ -d "$tmp/extract/data" ]; then + mkdir -p "$BUNDLE_DIR/tor/data-defaults" + cp -R "$tmp/extract/data/." "$BUNDLE_DIR/tor/data-defaults/" +fi + +cat > "$BUNDLE_DIR/TOR-EXPERT-BUNDLE.txt" < Date: Thu, 13 Aug 2026 14:35:49 -0300 Subject: release: verify bundled Tor signatures --- README.md | 6 ++-- docs/release-verification.md | 8 +++-- docs/tor.md | 9 ++++-- scripts/package-windows-tor.sh | 71 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 78 insertions(+), 16 deletions(-) (limited to 'docs/release-verification.md') diff --git a/README.md b/README.md index c30f171..bb6a4d4 100644 --- a/README.md +++ b/README.md @@ -462,8 +462,10 @@ make windows-tor That produces `Bitflash-*-windows-with-tor.zip`. The release script downloads the Tor Expert Bundle from the official Tor archive, verifies its pinned SHA256, -and places `tor/tor.exe` beside `Bitflash.exe` so `-managedtor` works without a -separate Tor install. +optionally verifies the Tor Project GPG signature when `gpg` is available, and +places `tor/tor.exe` beside `Bitflash.exe` so `-managedtor` works without a +separate Tor install. For release builds, use `TOR_VERIFY_GPG=required make +windows-tor` to require the extra signature check. --- diff --git a/docs/release-verification.md b/docs/release-verification.md index 04d18a3..b8eaf5e 100644 --- a/docs/release-verification.md +++ b/docs/release-verification.md @@ -83,9 +83,11 @@ key in `verify-release.sh`. For Windows releases with managed Tor built in, run `make windows-tor`. It creates `Bitflash-*-windows-with-tor.zip` by downloading the Tor Expert Bundle, -checking the pinned SHA256 in `scripts/package-windows-tor.sh`, and placing -`tor/tor.exe` next to `Bitflash.exe`. Include that zip in `SHA256SUMS` like any -other release asset. +checking the pinned SHA256 in `scripts/package-windows-tor.sh`, optionally +verifying the Tor Project `.asc` signature, and placing `tor/tor.exe` next to +`Bitflash.exe`. For release builds, run `TOR_VERIFY_GPG=required make +windows-tor` so the signature check is mandatory. Include that zip in +`SHA256SUMS` like any other release asset. ## Why this matters diff --git a/docs/tor.md b/docs/tor.md index be6a145..a408704 100644 --- a/docs/tor.md +++ b/docs/tor.md @@ -65,9 +65,12 @@ make windows-tor ``` The packaging script verifies a pinned SHA256 for the downloaded Tor Expert -Bundle before copying it into the release directory. The Tor binary is bundled; -the runtime data directory, hidden-service key, and control cookie are still -created under the user's Bitflash data directory. +Bundle before copying it into the release directory. When `gpg` is available it +also verifies the matching `.asc` signature against the pinned Tor Browser +Developers signing-key fingerprint. Release builds should use +`TOR_VERIFY_GPG=required make windows-tor` to make that second check mandatory. +The Tor binary is bundled; the runtime data directory, hidden-service key, and +control cookie are still created under the user's Bitflash data directory. To point at a specific Tor executable: diff --git a/scripts/package-windows-tor.sh b/scripts/package-windows-tor.sh index 084fd1a..c8cca3b 100755 --- a/scripts/package-windows-tor.sh +++ b/scripts/package-windows-tor.sh @@ -8,11 +8,15 @@ TOR_VERSION="${TOR_VERSION:-15.0.19}" TOR_ARCHIVE_NAME="tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz" TOR_URL="${TOR_URL:-https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/${TOR_ARCHIVE_NAME}}" TOR_SHA256="${TOR_SHA256:-6AC067402C7B4A3DC37887ED3754B3914B67FDC220C966190683E9CCF91ABF0F}" +TOR_ASC_URL="${TOR_ASC_URL:-${TOR_URL}.asc}" +TOR_SIGNING_KEY_FINGERPRINT="${TOR_SIGNING_KEY_FINGERPRINT:-EF6E286DDA85EA2A4BA7DE684E2C6E8793298290}" +TOR_VERIFY_GPG="${TOR_VERIFY_GPG:-auto}" BUNDLE_DIR="${BUNDLE_DIR:-$ROOT/Bitflash-${VERSION}-windows}" OUT_ZIP="${OUT_ZIP:-$ROOT/Bitflash-${VERSION}-windows-with-tor.zip}" CACHE_DIR="${CACHE_DIR:-$ROOT/.cache}" ARCHIVE="${TOR_ARCHIVE:-$CACHE_DIR/$TOR_ARCHIVE_NAME}" +ASC_FILE="${TOR_ASC:-$ARCHIVE.asc}" usage() { cat </dev/null 2>&1; then + curl -L --fail --output "$out" "$url" + elif command -v wget >/dev/null 2>&1; then + wget -O "$out" "$url" + else + echo "missing required command: curl or wget" >&2 + exit 1 + fi +} + if [ ! -d "$BUNDLE_DIR" ]; then echo "missing Windows release directory: $BUNDLE_DIR" >&2 echo "run 'make windows' first, or set BUNDLE_DIR" >&2 @@ -65,14 +85,7 @@ OUT_ZIP_ABS="$OUT_PARENT/$OUT_NAME" mkdir -p "$CACHE_DIR" if [ ! -f "$ARCHIVE" ]; then - if command -v curl >/dev/null 2>&1; then - curl -L --fail --output "$ARCHIVE" "$TOR_URL" - elif command -v wget >/dev/null 2>&1; then - wget -O "$ARCHIVE" "$TOR_URL" - else - echo "missing required command: curl or wget" >&2 - exit 1 - fi + download "$TOR_URL" "$ARCHIVE" fi got="$(sha256sum "$ARCHIVE" | awk '{print tolower($1)}')" @@ -87,6 +100,48 @@ fi tmp="$(mktemp -d "${TMPDIR:-/tmp}/bitflash-tor-package.XXXXXX")" trap 'rm -rf "$tmp"' EXIT +case "$TOR_VERIFY_GPG" in + auto|required|off) ;; + *) echo "TOR_VERIFY_GPG must be auto, required, or off" >&2; exit 2 ;; +esac + +if [ "$TOR_VERIFY_GPG" != "off" ]; then + if command -v gpg >/dev/null 2>&1; then + if [ ! -f "$ASC_FILE" ]; then + download "$TOR_ASC_URL" "$ASC_FILE" + fi + gnupg_home="$tmp/gnupg" + mkdir -p "$gnupg_home" + chmod 0700 "$gnupg_home" + gpg --homedir "$gnupg_home" --batch --auto-key-locate nodefault,wkd,keyserver \ + --locate-keys torbrowser@torproject.org >/dev/null 2>&1 || { + if [ "$TOR_VERIFY_GPG" = "required" ]; then + echo "could not import Tor Browser Developers signing key" >&2 + exit 1 + fi + echo "WARNING: skipped Tor GPG signature verification; signing key import failed" >&2 + } + if gpg --homedir "$gnupg_home" --batch --with-colons --fingerprint "$TOR_SIGNING_KEY_FINGERPRINT" \ + 2>/dev/null | grep -q "^fpr:::::::::${TOR_SIGNING_KEY_FINGERPRINT}:"; then + gpg --homedir "$gnupg_home" --batch --verify "$ASC_FILE" "$ARCHIVE" >/dev/null 2>&1 || { + echo "Tor archive GPG signature verification failed" >&2 + exit 1 + } + echo "Tor archive GPG signature verified against ${TOR_SIGNING_KEY_FINGERPRINT}" + elif [ "$TOR_VERIFY_GPG" = "required" ]; then + echo "Tor signing key fingerprint mismatch" >&2 + exit 1 + else + echo "WARNING: skipped Tor GPG signature verification; signing key fingerprint was not available" >&2 + fi + elif [ "$TOR_VERIFY_GPG" = "required" ]; then + echo "missing required command for TOR_VERIFY_GPG=required: gpg" >&2 + exit 1 + else + echo "WARNING: gpg not found; relying on pinned SHA256 only" >&2 + fi +fi + mkdir -p "$tmp/extract" tar -xzf "$ARCHIVE" -C "$tmp/extract" -- cgit v1.2.3