#!/bin/bash # ac-vault-unlock — Import GPG keys from USB and unlock the vault # Usage: # ac-vault-unlock Import keys from USB + unlock vault # ac-vault-unlock keys Copy GPG keys TO the USB (for bootstrapping) # ac-vault-unlock status Check if GPG key is imported and vault state set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)" VAULT_DIR="${REPO_DIR}/aesthetic-computer-vault" GPG_RECIPIENT="mail@aesthetic.computer" log() { echo -e "\033[0;36m[ac-vault-unlock]\033[0m $*"; } err() { echo -e "\033[0;31m[ac-vault-unlock]\033[0m $*" >&2; } find_usb_dev() { for dev in sda sdb sdc; do if [ -e "/sys/block/${dev}/removable" ]; then local rem=$(cat "/sys/block/${dev}/removable" 2>/dev/null) if [ "${rem}" = "1" ] && [ -e "/sys/block/${dev}" ]; then echo "/dev/${dev}" return 0 fi fi done if [ -e "/sys/block/sda" ]; then echo "/dev/sda" return 0 fi return 1 } docker_usb() { sudo docker run --rm --privileged -v /dev:/dev alpine:latest sh -c "$1" 2>&1 } check_gpg_key() { gpg --list-secret-keys "${GPG_RECIPIENT}" &>/dev/null } CMD="${1:-unlock}" case "${CMD}" in unlock) # Check if key is already imported if check_gpg_key; then log "GPG key already imported for ${GPG_RECIPIENT}" else log "GPG key not found — reading from USB..." USB_DEV="$(find_usb_dev)" || { err "No USB device found. Plug in your key USB."; exit 1; } # Extract private key from USB via docker TMPKEY=$(mktemp /tmp/gpg-import-XXXXXX.asc) trap "rm -f '${TMPKEY}'" EXIT CONTAINER=$(sudo docker create --privileged -v /dev:/dev alpine:latest sh -c " apk add --quiet dosfstools mkdir -p /mnt/usb mount ${USB_DEV}1 /mnt/usb if [ -f /mnt/usb/gpg/jeffrey-private.asc ]; then cat /mnt/usb/gpg/jeffrey-private.asc elif [ -f /mnt/usb/jeffrey-private.asc ]; then cat /mnt/usb/jeffrey-private.asc else echo 'KEY_NOT_FOUND' fi umount /mnt/usb ") sudo docker start -a "${CONTAINER}" > "${TMPKEY}" 2>/dev/null sudo docker rm "${CONTAINER}" &>/dev/null || true if grep -q "KEY_NOT_FOUND" "${TMPKEY}" || [ ! -s "${TMPKEY}" ]; then err "No GPG key found on USB." err "Expected: gpg/jeffrey-private.asc or jeffrey-private.asc" err "Run 'ac-vault-unlock keys' to copy keys to USB first." exit 1 fi log "Importing GPG key..." gpg --batch --import "${TMPKEY}" # Trust the key ultimately echo -e "5\ny\n" | gpg --batch --command-fd 0 --expert --edit-key "${GPG_RECIPIENT}" trust quit 2>/dev/null log "GPG key imported and trusted." fi # Unlock the vault if [ ! -d "${VAULT_DIR}" ]; then err "Vault not found at ${VAULT_DIR}" exit 1 fi cd "${VAULT_DIR}" log "Unlocking vault..." fish vault-tool.fish unlock log "Vault unlocked." ;; keys) # Copy GPG keys TO the USB for bootstrapping USB_DEV="$(find_usb_dev)" || { err "No USB device found."; exit 1; } # Get keys from vault (must be decrypted) or from GPG keyring TMPDIR=$(mktemp -d /tmp/gpg-export-XXXXXX) trap "rm -rf '${TMPDIR}'" EXIT if [ -f "${VAULT_DIR}/gpg/jeffrey-private.asc" ]; then log "Using keys from vault..." cp "${VAULT_DIR}/gpg/jeffrey-private.asc" "${TMPDIR}/" cp "${VAULT_DIR}/gpg/jeffrey-public.asc" "${TMPDIR}/" elif check_gpg_key; then log "Exporting keys from GPG keyring..." gpg --armor --export "${GPG_RECIPIENT}" > "${TMPDIR}/jeffrey-public.asc" gpg --armor --export-secret-keys "${GPG_RECIPIENT}" > "${TMPDIR}/jeffrey-private.asc" else err "No keys available. Import keys first or unlock the vault." exit 1 fi log "Writing keys to USB ${USB_DEV}..." CONTAINER=$(sudo docker create --privileged -v /dev:/dev alpine:latest sh -c " apk add --quiet dosfstools mtools mkdir -p /mnt/usb mount ${USB_DEV}1 /mnt/usb mkdir -p /mnt/usb/gpg cp /tmp/jeffrey-private.asc /mnt/usb/gpg/ cp /tmp/jeffrey-public.asc /mnt/usb/gpg/ sync ls -la /mnt/usb/gpg/ umount /mnt/usb ") sudo docker cp "${TMPDIR}/jeffrey-private.asc" "${CONTAINER}:/tmp/jeffrey-private.asc" sudo docker cp "${TMPDIR}/jeffrey-public.asc" "${CONTAINER}:/tmp/jeffrey-public.asc" sudo docker start -a "${CONTAINER}" 2>&1 sudo docker rm "${CONTAINER}" &>/dev/null || true log "GPG keys written to USB at gpg/" ;; status) echo "=== GPG Key ===" if check_gpg_key; then gpg --list-secret-keys "${GPG_RECIPIENT}" 2>/dev/null echo "" echo "Status: IMPORTED" else echo "Status: NOT IMPORTED" fi echo "" echo "=== Vault ===" if [ -d "${VAULT_DIR}" ]; then cd "${VAULT_DIR}" fish vault-tool.fish status 2>/dev/null || echo "vault-tool.fish not found" else echo "Vault directory not found" fi echo "" echo "=== USB ===" USB_DEV="$(find_usb_dev 2>/dev/null)" && { echo "USB device: ${USB_DEV}" docker_usb " apk add --quiet dosfstools mkdir -p /mnt/usb mount ${USB_DEV}1 /mnt/usb 2>/dev/null && { if [ -f /mnt/usb/gpg/jeffrey-private.asc ]; then echo 'GPG keys: FOUND at gpg/' elif [ -f /mnt/usb/jeffrey-private.asc ]; then echo 'GPG keys: FOUND at root' else echo 'GPG keys: NOT FOUND' fi umount /mnt/usb } || echo 'Could not mount partition' " } || echo "No USB detected" ;; *) echo "Usage: ac-vault-unlock {unlock|keys|status}" echo "" echo "Commands:" echo " unlock Import GPG keys from USB + unlock vault (default)" echo " keys Copy GPG keys TO the USB (for bootstrapping)" echo " status Check GPG key, vault, and USB state" exit 1 ;; esac