alpha
Login
or
Join now
lass.pds.lassul.us
/
superconfig
Star
0
Fork
1
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
This repository has no description
Star
0
Fork
1
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
1
Pipelines
tools.ssh-with-age: RIP
author
lassulus
date
7 months ago
(Mar 10, 2026, 10:36 AM CET)
commit
64e82c5e
64e82c5e82d7a3d9e24681749b858e9d30d68539
parent
28f7563b
28f7563b5e21af5028ed2e4cb26a113d85385f95
-142
2 changed files
Expand all
Collapse all
Unified
Split
tools
ssh-with-age
flake-module.nix
usage.kdl
-134
tools/ssh-with-age/flake-module.nix
Reviewed
···
1
1
-
{ self, ... }:
2
2
-
{
3
3
-
perSystem =
4
4
-
{ pkgs, ... }:
5
5
-
let
6
6
-
lib = pkgs.lib;
7
7
-
8
8
-
# Generate key entries from flake structure
9
9
-
sshKeyEntries = lib.concatStringsSep "\n" (
10
10
-
lib.mapAttrsToList (
11
11
-
name: key:
12
12
-
if key.encrypted && key.private != null then
13
13
-
''
14
14
-
["${name}"]="${key.private}"
15
15
-
''
16
16
-
else
17
17
-
""
18
18
-
) self.keys.ssh
19
19
-
);
20
20
-
in
21
21
-
{
22
22
-
packages.ssh-with-age = (pkgs.writeShellApplication {
23
23
-
name = "ssh-with-age";
24
24
-
runtimeInputs = [
25
25
-
pkgs.openssh
26
26
-
pkgs.age
27
27
-
pkgs.age-plugin-se
28
28
-
pkgs.age-plugin-yubikey
29
29
-
pkgs.libfido2
30
30
-
];
31
31
-
text = ''
32
32
-
# SSH wrapper that tries each encrypted SSH key with the connected FIDO2 device
33
33
-
34
34
-
# Key mapping from flake
35
35
-
declare -A SSH_KEYS
36
36
-
${sshKeyEntries}
37
37
-
38
38
-
usage() {
39
39
-
echo "Usage: ssh-with-age [ssh_options...] destination"
40
40
-
echo " ssh-with-age --list-keys"
41
41
-
echo " ssh-with-age --list-devices"
42
42
-
echo ""
43
43
-
echo "Tries each encrypted SSH key to find one that works with the connected FIDO2 device."
44
44
-
exit 1
45
45
-
}
46
46
-
47
47
-
list_keys() {
48
48
-
echo "Available encrypted SSH keys:"
49
49
-
for key in "''${!SSH_KEYS[@]}"; do
50
50
-
echo " $key"
51
51
-
done
52
52
-
}
53
53
-
54
54
-
list_devices() {
55
55
-
echo "Connected FIDO2 devices:"
56
56
-
fido2-token -L
57
57
-
}
58
58
-
59
59
-
if [[ "$1" == "--list-keys" ]]; then
60
60
-
list_keys
61
61
-
exit 0
62
62
-
fi
63
63
-
64
64
-
if [[ "$1" == "--list-devices" ]]; then
65
65
-
list_devices
66
66
-
exit 0
67
67
-
fi
68
68
-
69
69
-
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
70
70
-
usage
71
71
-
fi
72
72
-
73
73
-
# Create temporary file for decrypted key
74
74
-
temp_key=$(mktemp)
75
75
-
trap 'rm -f "$temp_key"' EXIT
76
76
-
77
77
-
# Try each encrypted SSH key
78
78
-
found_key=""
79
79
-
for key_name in "''${!SSH_KEYS[@]}"; do
80
80
-
encrypted_key="''${SSH_KEYS[$key_name]}"
81
81
-
82
82
-
if [[ ! -f "$encrypted_key" ]]; then
83
83
-
continue
84
84
-
fi
85
85
-
86
86
-
echo "Trying key: $key_name..."
87
87
-
88
88
-
# Try to decrypt with hardware plugins
89
89
-
decrypted=false
90
90
-
# Try each hardware plugin method
91
91
-
if age -d -j fido2-hmac "$encrypted_key" > "$temp_key" 2>/dev/null || \
92
92
-
age -d -j se "$encrypted_key" > "$temp_key" 2>/dev/null || \
93
93
-
age -d -j yubikey "$encrypted_key" > "$temp_key" 2>/dev/null; then
94
94
-
decrypted=true
95
95
-
fi
96
96
-
97
97
-
if [[ "$decrypted" == "true" ]]; then
98
98
-
99
99
-
# Check if this is a FIDO2 key by looking at the key type
100
100
-
if grep -q "sk-" "$temp_key"; then
101
101
-
# Try to use the key with SSH agent to verify it works with connected device
102
102
-
chmod 600 "$temp_key"
103
103
-
104
104
-
# Test if the key works by trying ssh-add
105
105
-
if SSH_ASKPASS=/bin/false ssh-add -T "$temp_key" 2>/dev/null; then
106
106
-
found_key="$key_name"
107
107
-
echo "✓ Found working key: $key_name"
108
108
-
break
109
109
-
else
110
110
-
echo " Key $key_name requires a different FIDO2 device"
111
111
-
fi
112
112
-
else
113
113
-
echo " Key $key_name is not a FIDO2 key"
114
114
-
fi
115
115
-
else
116
116
-
echo " Could not decrypt $key_name (missing age identity?)"
117
117
-
fi
118
118
-
done
119
119
-
120
120
-
if [[ -z "$found_key" ]]; then
121
121
-
echo "No matching SSH key found for the connected FIDO2 device." >&2
122
122
-
echo "Make sure:" >&2
123
123
-
echo " 1. Your FIDO2 device is connected" >&2
124
124
-
echo " 2. You have the correct age identity to decrypt the keys" >&2
125
125
-
echo " 3. The SSH key was generated with this FIDO2 device" >&2
126
126
-
exit 1
127
127
-
fi
128
128
-
129
129
-
# Use the found key with SSH
130
130
-
ssh -i "$temp_key" "$@"
131
131
-
'';
132
132
-
}).overrideAttrs { passthru.usage = builtins.readFile ./usage.kdl; };
133
133
-
};
134
134
-
}
-8
tools/ssh-with-age/usage.kdl
Reviewed
···
1
1
-
bin "ssh-with-age"
2
2
-
about "SSH wrapper that tries each encrypted SSH key with the connected FIDO2 device"
3
3
-
4
4
-
flag "--list-keys" help="List available encrypted SSH keys"
5
5
-
flag "--list-devices" help="List connected FIDO2 devices"
6
6
-
flag "-h --help" help="Show help message"
7
7
-
8
8
-
arg "[ssh_options...]" help="SSH options and destination" var=#true