From d59e250ab305d9c74d0336eeedd6dffe896ba410 Mon Sep 17 00:00:00 2001 From: Mohammad Shafiee Date: Wed, 22 Jul 2026 13:45:53 +0200 Subject: [PATCH] chore(apt): add GPG signing public key and setup script --- public.key | 64 ++++++++++++++++++++++ scripts/setup-gpg-keys.sh | 112 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 public.key create mode 100755 scripts/setup-gpg-keys.sh diff --git a/public.key b/public.key new file mode 100644 index 0000000..19c9f0e --- /dev/null +++ b/public.key @@ -0,0 +1,64 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +rdtB4A== +=lrzs +-----END PGP PUBLIC KEY BLOCK----- diff --git a/scripts/setup-gpg-keys.sh b/scripts/setup-gpg-keys.sh new file mode 100755 index 0000000..dbcd8d5 --- /dev/null +++ b/scripts/setup-gpg-keys.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +set -euo pipefail + +KEY_NAME="Zurvan Linux Archive" +KEY_EMAIL="archive@zurvanlinux.org" +KEY_LENGTH=4096 + +if gpg --list-keys "${KEY_EMAIL}" >/dev/null 2>&1; then + FPR=$(gpg --list-keys --with-colons "${KEY_EMAIL}" | awk -F: '/^pub:/ {print $10; exit}') + echo "ERROR: A key for ${KEY_EMAIL} already exists in this keyring." + echo " Aborting to avoid overwriting. Remove it first if intended:" + echo " gpg --batch --yes --delete-secret-keys ${FPR}" + echo " gpg --batch --yes --delete-keys ${FPR}" + exit 1 +fi + +cat > /tmp/gpg-batch-primary-$$ < /tmp/gpg-addkey-$$.exp < " +send "addkey\r" +expect "keyt" +send "4\r" +expect "keys" +send "${KEY_LENGTH}\r" +expect "expire" +send "0\r" +expect "y/N" +send "y\r" +expect "y/N" +send "y\r" +expect "gpg> " +send "save\r" +expect eof +EOF +chmod +x /tmp/gpg-addkey-$$.exp + +echo "[*] Adding signing-only subkey ..." +/tmp/gpg-addkey-$$.exp "${PRIMARY_KEYID}" + +SUBKEY_FPR=$(gpg --list-keys --with-colons "${KEY_EMAIL}" | awk -F: '/^sub:/ {print $5; exit}') +echo "=== Signing subkey fingerprint: ${SUBKEY_FPR} ===" + +OUT_DIR="$(cd "$(dirname "$0")/.." && pwd)" + +echo "[*] Exporting public key -> ${OUT_DIR}/public.key" +gpg --armor --export "${KEY_EMAIL}" > "${OUT_DIR}/public.key" + +echo "[*] Exporting secret subkey -> ${OUT_DIR}/secret-subkey.asc" +gpg --armor --export-secret-subkeys "${PRIMARY_KEYID}" > "${OUT_DIR}/secret-subkey.asc" || true +if [[ ! -s "${OUT_DIR}/secret-subkey.asc" ]]; then + echo "ERROR: Failed to export secret subkey." >&2 + exit 1 +fi + +chmod 600 "${OUT_DIR}/public.key" "${OUT_DIR}/secret-subkey.asc" + +cat < Secrets and variables -> Actions -> New repository secret + + Name: APT_SIGNING_SUBKEY + Value: contents of secret-subkey.asc (the whole armored block) + + Name: APT_SIGNING_PASSPHRASE + Value: leave blank / unset unless the exported subkey is passphrase-protected + (the publish-repo.yml worklow invokes gpg with --pinentry-mode loopback + and APT_SIGNING_PASSPHRASE at signing time). + +4. Keep the primary key offline / air-gapped permanently. + If the subkey leaks, revoke it from the offline primary key and + generate a new signing subkey. + +5. Re-run .github/workflows/publish-repo.yml to verify signing works. +============================================================= +EOF