forked from
lass.pds.lassul.us/superconfig
This repository has no description
4.0 kB
110 lines
1#!/usr/bin/env bash
2set -euo pipefail
3
4# age-detect: Detects connected age-compatible security keys
5# Returns identity file path and detected key information
6
7# Function to detect connected security keys and their age identities
8detect_age_keys() {
9 local temp_identities
10 temp_identities=$(mktemp)
11
12 # Check for Secure Enclave on macOS (highest priority)
13 if [[ "$(uname)" == "Darwin" ]] && command -v age-plugin-se >/dev/null 2>&1; then
14 rm -f "$temp_identities"
15 echo "DETECTED_KEY=se"
16 echo "KEY_TYPE=se"
17 return
18 fi
19
20 # Check for TPM on Linux (second priority - built-in, no USB needed)
21 # Requires: TPM device, hostname.age with age1tpm1/age1tag1 recipient, and identity in ~/.config/age/
22 # Newer age-plugin-tpm emits native p256tag (age1tag1) recipients by default.
23 if [[ -c /dev/tpmrm0 ]] && [[ -f ~/.config/age/tpm-identity.txt ]]; then
24 local hostname_key
25 hostname_key="${AGE_DETECT_KEYS_DIR:-}/age/$(hostname).age"
26 if [[ -f "$hostname_key" ]] && grep -qE "^age1(tpm|tag)1" "$hostname_key" 2>/dev/null; then
27 rm -f "$temp_identities"
28 echo "DETECTED_KEY=tpm"
29 echo "KEY_TYPE=tpm"
30 return
31 fi
32 fi
33
34 # Check for gpg-agent with an encryption subkey (third priority).
35 # Frictionless after the first decrypt because gpg-agent caches the
36 # passphrase / smartcard PIN, so we prefer it over yubikey/solo2.
37 if command -v gpg-connect-agent >/dev/null 2>&1 \
38 && gpg-connect-agent /bye >/dev/null 2>&1 \
39 && gpg --list-secret-keys --with-colons 2>/dev/null \
40 | awk -F: '$1 == "ssb" && $12 ~ /e/ { found=1 } END { exit !found }'; then
41 echo "AGE-PLUGIN-GPG-1H40XPM" > "$temp_identities"
42 echo "IDENTITY_FILE=$temp_identities"
43 echo "DETECTED_KEY=gpg"
44 echo "KEY_TYPE=gpg"
45 return
46 fi
47
48 # Check for YubiKeys (fourth priority)
49 if command -v ykman >/dev/null 2>&1; then
50 local yubikey_serial
51 yubikey_serial=$(ykman info 2>/dev/null | grep "Serial number:" | cut -d: -f2 | tr -d ' ' || true)
52 if [[ -n "$yubikey_serial" ]]; then
53 echo "AGE-PLUGIN-YUBIKEY-1M2PLUQYZ242EPUSSHDFWJ" > "$temp_identities"
54 echo "IDENTITY_FILE=$temp_identities"
55 case "$yubikey_serial" in
56 "16679898")
57 echo "DETECTED_KEY=yubi1"
58 ;;
59 "11342136")
60 echo "DETECTED_KEY=yubi2"
61 ;;
62 *)
63 echo "DETECTED_KEY=yubikey-${yubikey_serial}"
64 ;;
65 esac
66 echo "KEY_TYPE=yubikey"
67 return
68 fi
69 fi
70
71 # Check for Solo2 (lowest priority)
72 if command -v fido2-token >/dev/null 2>&1; then
73 if fido2-token -L 2>/dev/null | grep -q "Solo 2"; then
74 # FIDO2-HMAC doesn't use identity file
75 rm -f "$temp_identities"
76 echo "IDENTITY_FILE="
77 echo "DETECTED_KEY=solo2"
78 echo "KEY_TYPE=solo2"
79 return
80 fi
81 fi
82
83 # No keys detected
84 rm -f "$temp_identities"
85 echo "IDENTITY_FILE="
86 echo "DETECTED_KEY="
87 echo "KEY_TYPE="
88}
89
90# Parse command line arguments
91case "${1:-detect}" in
92 detect)
93 detect_age_keys
94 ;;
95 --help|-h)
96 echo "Usage: age-detect [detect]"
97 echo ""
98 echo "Detects the first available age-compatible security key and outputs:"
99 echo " IDENTITY_FILE=<path> - Path to temporary identity file for age (empty for Solo2)"
100 echo " DETECTED_KEY=<name> - Name of the detected key (e.g., yubi1, solo2, se)"
101 echo " KEY_TYPE=<type> - Type of key (yubikey, solo2, se)"
102 echo ""
103 echo "Priority order: se > tpm > gpg > yubikey > solo2"
104 ;;
105 *)
106 echo "Unknown command: $1" >&2
107 echo "Use --help for usage information" >&2
108 exit 1
109 ;;
110esac