#!/usr/bin/env bash # # decrypt.sh — Decrypt a PGP-encrypted attachment using the private key in this # folder. The private key is passphrase-protected; the passphrase is read from a # separate file (default: passphrase.txt). # # Usage: # ./decrypt.sh [ENCRYPTED_FILE] [OUTPUT_FILE] # # ENCRYPTED_FILE Path to the .pgp/.gpg/.asc file to decrypt. # Defaults to the single *.pgp file in this folder. # OUTPUT_FILE Where to write the decrypted result. # Defaults to ENCRYPTED_FILE with its .pgp/.gpg suffix removed. # # The script imports the key into a throwaway, isolated GnuPG home so it never # touches your real ~/.gnupg keyring, then removes it on exit. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" KEY_FILE="${KEY_FILE:-$SCRIPT_DIR/pgp-secret-keys.asc}" PASSPHRASE_FILE="${PASSPHRASE_FILE:-$SCRIPT_DIR/passphrase.txt}" die() { echo "Error: $*" >&2; exit 1; } command -v gpg >/dev/null 2>&1 || die "gpg is not installed (try: brew install gnupg)" [ -f "$KEY_FILE" ] || die "private key not found: $KEY_FILE" [ -f "$PASSPHRASE_FILE" ] || die "passphrase file not found: $PASSPHRASE_FILE (create it and put the key passphrase inside)" # --- Resolve the encrypted input file --------------------------------------- ENC_FILE="${1:-}" if [ -z "$ENC_FILE" ]; then # Auto-pick the single *.pgp in this folder. shopt -s nullglob candidates=("$SCRIPT_DIR"/*.pgp) shopt -u nullglob case "${#candidates[@]}" in 0) die "no *.pgp file found in $SCRIPT_DIR — pass the file as the first argument" ;; 1) ENC_FILE="${candidates[0]}" ;; *) die "multiple *.pgp files found — pass the one to decrypt as the first argument" ;; esac fi [ -f "$ENC_FILE" ] || die "encrypted file not found: $ENC_FILE" # --- Resolve the output file ------------------------------------------------- OUT_FILE="${2:-}" if [ -z "$OUT_FILE" ]; then case "$ENC_FILE" in *.pgp) OUT_FILE="${ENC_FILE%.pgp}" ;; *.gpg) OUT_FILE="${ENC_FILE%.gpg}" ;; *.asc) OUT_FILE="${ENC_FILE%.asc}" ;; *) OUT_FILE="${ENC_FILE}.decrypted" ;; esac fi # Read passphrase from the separate file (strip a single trailing newline). PASSPHRASE="$(cat "$PASSPHRASE_FILE")" [ -n "$PASSPHRASE" ] || die "passphrase file is empty: $PASSPHRASE_FILE" # --- Isolated, throwaway keyring -------------------------------------------- GNUPGHOME="$(mktemp -d)" export GNUPGHOME chmod 700 "$GNUPGHOME" cleanup() { rm -rf "$GNUPGHOME"; } trap cleanup EXIT echo "Importing private key ..." >&2 gpg --batch --quiet --import "$KEY_FILE" echo "Decrypting: $(basename "$ENC_FILE")" >&2 gpg --batch --yes --quiet \ --pinentry-mode loopback \ --passphrase-fd 3 \ --output "$OUT_FILE" \ --decrypt "$ENC_FILE" 3<<<"$PASSPHRASE" echo "Decrypted -> $OUT_FILE" >&2