From 4c9031fda271ed7d4503642f63ff824faa6cc3a0 Mon Sep 17 00:00:00 2001 From: "David S. H. Rosenthal" Date: Wed, 6 Nov 2024 10:19:17 +0000 Subject: [PATCH] scripts: add download-check-artifact.sh script MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit While checking wiki documentation about GPG signatures checking I found this nice script and I've thought, that it would be nice to provide it officially instead of some random internet site. Usage example: $ ./scripts/download-check-artifact.sh https://downloads.openwrt.org/snapshots/targets/mediatek/filogic/openwrt-mediatek-filogic-openwrt_one-squashfs-sysupgrade.itb 1) Downloading image file ========================= ########################################### 100.0% 2) Downloading checksum file ============================ ########################################### 100.0% 3) Downloading the GPG signature ================================ ########################################### 100.0% 4) Verifying GPG signature ========================== gpg: Signature made Tue 05 Nov 2024 05:21:50 PM UTC gpg: using EDDSA key 92C561DE55AE6552F3C736B82B0151090606D1D9 gpg: Good signature from "OpenWrt Build System (Nitrokey3) " [ultimate] Primary key fingerprint: 8A8B C12F 46B8 36C0 F9CD B36F 1D53 D187 7742 E911 Subkey fingerprint: 92C5 61DE 55AE 6552 F3C7 36B8 2B01 5109 0606 D1D9 5) Verifying SHA256 checksum ============================ openwrt-mediatek-filogic-openwrt_one-squashfs-sysupgrade.itb: OK Verification done! ================== Downloaded artifact placed in '/var/home/ynezz/dev/openwrt/openwrt.git/openwrt-mediatek-filogic-openwrt_one-squashfs-sysupgrade.itb' Cleaning up. Adding file in a state as downloaded from https://www.abitare.org/bin/download.sh References: https://openwrt.org/docs/guide-quick-start/verify_firmware_checksum?s[]=gpg#linux Signed-off-by: David S. H. Rosenthal Link: https://github.com/openwrt/openwrt/pull/16871 Signed-off-by: Petr Å tetiar --- scripts/download-check-artifact.sh | 154 +++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100755 scripts/download-check-artifact.sh diff --git a/scripts/download-check-artifact.sh b/scripts/download-check-artifact.sh new file mode 100755 index 0000000000..31868da5cd --- /dev/null +++ b/scripts/download-check-artifact.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +# Script to perform verified file downloads. +# Exit codes: +# 0 - File downloaded successfully and verified +# 1 - Failed to download requested file +# 2 - Failed to download sha256sums file +# 3 - Failed to download sha256sums.gpg file +# 4 - GnuPG is available but fails to verify the signature (missing pubkey, file integrity error, ...) +# 5 - The checksums do not match +# 6 - Unable to copy the requested file to its final destination +# 254 - The script got interrupted by a signal +# 255 - A suitable download or checksum utility is missing + +[ -n "$1" ] || { + echo "Usage: $0 " >&2 + exit 1 +} + +finish() { + [ -e "/tmp/verify.$$" ] && { + echo "Cleaning up." + rm -r "/tmp/verify.$$" + } + exit $1 +} + +trap "finish 254" INT TERM + +destdir="$(pwd)" +image_url="$1" +image_file="${image_url##*/}" +sha256_url="${image_url%/*}/sha256sums" +gpgsig_url="${image_url%/*}/sha256sums.asc" +keyserver_url="hkp://keyserver.ubuntu.com" + +# Find a suitable download utility +if which curl >/dev/null; then + download() { curl --progress-bar -o "$1" "$2"; } +elif which wget >/dev/null; then + download() { wget -O "$1" "$2"; } +elif which fetch >/dev/null; then + download() { fetch -o "$1" "$2"; } +else + echo "No suitable download utility found, cannot download files!" >&2 + finish 255 +fi + +# Find a suitable checksum utility +if which sha256sum >/dev/null; then + checksum() { sha256sum -c --ignore-missing "sha256sums"; } +elif which shasum >/dev/null; then + checksum() { + local sum="$(shasum -a 256 "$image_file")"; + grep -xF "${sum%% *} *$image_file" "sha256sums"; + } +else + echo "No SHA256 checksum executable installed, cannot verify checksums!" >&2 + finish 255 +fi + +# Check for gpg availability +if which gpg >/dev/null; then + runpgp() { gpg "$@"; } +else + runpgp() { + echo "WARNING: No GnuPG installed, cannot verify digital signature!" >&2 + return 0 + } +fi + +mkdir -p "/tmp/verify.$$" +cd "/tmp/verify.$$" + +echo "" +echo "1) Downloading image file" +echo "=========================" +download "$image_file" "$image_url" || { + echo "Failed to download image file!" >&2 + finish 1 +} + +echo "" +echo "2) Downloading checksum file" +echo "============================" +download "sha256sums" "$sha256_url" || { + echo "Failed to download checksum file!" >&2 + finish 2 +} + +echo "" +echo "3) Downloading the GPG signature" +echo "================================" +download "sha256sums.gpg" "$gpgsig_url" || { + echo "Failed to download GPG signature!" >&2 + finish 3 +} + +echo "" +echo "4) Verifying GPG signature" +echo "==========================" +missing_key=$(runpgp --status-fd 1 --with-fingerprint --verify \ + "sha256sums.gpg" "sha256sums" 2>/dev/null | sed -ne 's!^.* NO_PUBKEY !!p') + +if [ -n "$missing_key" ]; then + echo "The signature was signed by a public key with the id $missing_key" >&2 + echo "which is not present on this system." >&2 + echo "" >&2 + + echo "Provide a public keyserver url below or press enter to accept the" >&2 + echo "default suggestion. Hit Ctrl-C to abort the operation." >&2 + echo "" >&2 + + while true; do + printf "Keyserver to use? [$keyserver_url] > " + read url; case "${url:-$keyserver_url}" in + hkp://*) + gpg --keyserver "${url:-$keyserver_url}" --recv-keys "$missing_key" || { + echo "Failed to download public key." >&2 + finish 7 + } + break + ;; + *) + echo "Expecting a key server url in the form 'hkp://hostname'." >&2 + ;; + esac + done +fi + +runpgp --with-fingerprint --verify "sha256sums.gpg" "sha256sums" || { + echo "Failed to verify checksum file with GPG signature!" >&2 + finish 4 +} + +echo "" +echo "5) Verifying SHA256 checksum" +echo "============================" +checksum || { + echo "Checksums do not match!" >&2 + finish 5 +} + +cp "$image_file" "$destdir/$image_file" || { + echo "Failed to write '$destdir/$image_file'" >&2 + finish 6 +} + +echo "" +echo "Verification done!" +echo "==================" +echo "Firmware image placed in '$destdir/$image_file'." +echo "" + +finish 0 -- 2.30.2