Marco Ricci commited on 2024-11-23 18:50:10
Zeige 4 geänderte Dateien mit 186 Einfügungen und 7 Löschungen.
We explain the necessary software/operating system prerequisites and configurations. We further prominently note that Windows is currently not supported, and that `gpg-agent` behaves differently than other agents in regard to SSH key management. We further clean up the list of future work, and ensure styling consistency with the basic setup (passphrase) tutorial.
... | ... |
@@ -47,12 +47,11 @@ |
47 | 47 |
|
48 | 48 |
### Tutorials |
49 | 49 |
|
50 |
-* [Setting up `derivepassphrase` from scratch for three existing accounts, with a master passphrase](tutorials/basic-setup-passphrase.md) |
|
51 |
-* Setting up `derivepassphrase` from scratch for three existing accounts, with a new SSH key |
|
50 |
+* [Setting up `derivepassphrase vault` from scratch for three existing accounts, with a master passphrase](tutorials/basic-setup-passphrase.md) |
|
52 | 51 |
|
53 | 52 |
### How-tos |
54 | 53 |
|
55 |
-* How to set up `derivepassphrase` with an SSH key |
|
54 |
+* [How to set up `derivepassphrase vault` with an SSH key](how-tos/ssh-key.md) |
|
56 | 55 |
* How to choose a good service name |
57 | 56 |
* How to edit a saved `derivepassphrase vault` configuration correctly |
58 | 57 |
* How to deal with "supported" and "unsupported" special characters |
... | ... |
@@ -67,4 +66,3 @@ |
67 | 66 |
* Security aspects and other tradeoffs when using deterministic password generators |
68 | 67 |
* Tradeoffs between a master passphrase and a master SSH key |
69 | 68 |
* Why is `vault`'s `--repeat` option named this way if it counts occurrences, not repetitions? |
70 |
-* Why are master SSH keys not supported under Windows? |
... | ... |
@@ -0,0 +1,181 @@ |
1 |
+# How to set up `derivepassphrase vault` with an SSH key |
|
2 |
+ |
|
3 |
+## Prerequisites |
|
4 |
+ |
|
5 |
+!!! abstract "See also" |
|
6 |
+ |
|
7 |
+ → Tradeoffs between a master passphrase and a master SSH key (TODO) |
|
8 |
+ |
|
9 |
+ 1. [A running SSH agent; typically provided by OpenSSH or |
|
10 |
+ PuTTY.](#prereq-ssh-agent) |
|
11 |
+ 2. [A Python installation that can talk to the SSH |
|
12 |
+ agent.](#prereq-python-support) |
|
13 |
+ 3. [A supported SSH key; typically an RSA, Ed25519 or Ed448 |
|
14 |
+ key.](#prereq-ssh-key) |
|
15 |
+ |
|
16 |
+### A running SSH agent { #prereq-ssh-agent } |
|
17 |
+ |
|
18 |
+Install an SSH agent, which is usually part of an SSH client |
|
19 |
+distribution. `ssh-agent` from [OpenSSH][], Pageant from [PuTTY][] and |
|
20 |
+`gpg-agent` (v2) from [GnuPG][] are known to work. If in doubt, choose |
|
21 |
+OpenSSH. |
|
22 |
+ |
|
23 |
+??? note "Agent-specific features" |
|
24 |
+ |
|
25 |
+ * OpenSSH's `ssh-agent` supports limiting the time the agent holds |
|
26 |
+ the key in memory ("key lifetime"). Such usage is *recommended*. |
|
27 |
+ * `ssh-agent` and GnuPG's `gpg-agent` support requiring confirmation |
|
28 |
+ upon each use for a specific key. Such usage is *also |
|
29 |
+ recommended*. |
|
30 |
+ |
|
31 |
+??? note "Other agent-specific notes" |
|
32 |
+ |
|
33 |
+ === "GnuPG/`gpg-agent`" |
|
34 |
+ |
|
35 |
+ * `gpg-agent` v2.0 and later uses a *persistent* database of |
|
36 |
+ known keys, SSH or otherwise. "Adding" a key to the agent |
|
37 |
+ actually means *importing* it, and requires choosing an |
|
38 |
+ "import passphrase" to protect the key on disk, in the |
|
39 |
+ persistent database. `gpg-agent` will cache the import |
|
40 |
+ passphrase in memory, and if that cache entry expires, then |
|
41 |
+ the *import passphrase* must be provided to unlock the key. |
|
42 |
+ * As a design consequence, `gpg-agent` always lists all known |
|
43 |
+ SSH keys as available in the agent. It is impossible to |
|
44 |
+ remove an SSH key from `gpg-agent` using standard SSH agent |
|
45 |
+ operations. |
|
46 |
+ |
|
47 |
+### A Python installation that can talk to the SSH agent { #prereq-python-support } |
|
48 |
+ |
|
49 |
+On non-Windows operating systems, your Python installation must support |
|
50 |
+UNIX domain sockets (the `socket.AF_UNIX` symbol). The SSH agent must |
|
51 |
+expose its communication socket via the `SSH_AUTH_SOCK` environment |
|
52 |
+variable. |
|
53 |
+ |
|
54 |
+??? bug "Windows is currently *not* supported" |
|
55 |
+ |
|
56 |
+ [→ Issue `the-13th-letter/derivepassphrase#13`: Support |
|
57 |
+ PuTTY/Pageant on Windows][ISSUE_WINDOWS_SUPPORT] |
|
58 |
+ |
|
59 |
+ The two major SSH agents on Windows (PuTTY/Pageant and OpenSSH) use |
|
60 |
+ <i>Windows named pipes</i> for communication, and Python on Windows |
|
61 |
+ does not inherently support named pipes. No comprehensive |
|
62 |
+ third-party modules to interface with named pipes appears to exist, |
|
63 |
+ so teaching `derivepassphrase` to use Windows named pipes will |
|
64 |
+ require us developers to write a custom (C?) module specific to this |
|
65 |
+ application---an unrealistic task if we lack both technical know-how |
|
66 |
+ for the named pipe API as well as Windows hardware to test any |
|
67 |
+ potential implementation on. |
|
68 |
+ |
|
69 |
+### A supported SSH key { #prereq-ssh-key } |
|
70 |
+ |
|
71 |
+For an SSH key to be usable by `derivepassphrase`, the SSH agent must |
|
72 |
+always generate the same signature for the same input, i.e. the |
|
73 |
+signature must be deterministic for this key type. Commonly used SSH |
|
74 |
+types include RSA, DSA, ECDSA, Ed25519 and Ed448. |
|
75 |
+ |
|
76 |
+* RSA, Ed25519 and Ed448 signatures are deterministic by definition. |
|
77 |
+ Thus RSA, Ed25519 and Ed448 keys are suitable under any SSH agent. |
|
78 |
+ |
|
79 |
+* DSA and ECDSA signatures require choosing a value specific to each |
|
80 |
+ signature (a "cryptographic nonce"), which must be unpredictable. |
|
81 |
+ Typical DSA/ECDSA implementations therefore generate a suitably large |
|
82 |
+ random number as the nonce. This makes signatures non-deterministic, |
|
83 |
+ and thus unsuitable for `derivepassphrase`. |
|
84 |
+ |
|
85 |
+ ??? info "Exception: PuTTY/Pageant and RFC 6979" |
|
86 |
+ |
|
87 |
+ [RFC 6979][] specifies a method to *calculate* the nonce from |
|
88 |
+ the DSA/ECDSA key and the message to be signed. DSA/ECDSA |
|
89 |
+ signatures from SSH agents implementing RFC 6979 are therefore |
|
90 |
+ deterministic, and thus *also* suitable for `derivepassphrase`. |
|
91 |
+ Pageant 0.81 implements RFC 6979. |
|
92 |
+ |
|
93 |
+ !!! warning "Warning: Pageant < 0.81" |
|
94 |
+ |
|
95 |
+ Pageant 0.80 and earlier uses a different, homegrown method |
|
96 |
+ to calculate the nonce deterministically. Those versions |
|
97 |
+ are *also* prinicipally suitable for use with |
|
98 |
+ `derivepassphrase`, but **they generate different signatures |
|
99 |
+ -- and different derived passphrases -- than Pageant 0.81 |
|
100 |
+ and later**. |
|
101 |
+ |
|
102 |
+## Configuring `derivepassphrase vault` to use an SSH key |
|
103 |
+ |
|
104 |
+Assuming the [prerequisites above](#prerequisites) are satisfied, ensure |
|
105 |
+that the SSH agent is running, the SSH key is loaded into the agent, and |
|
106 |
+the `SSH_AUTH_SOCK` environment variable is correctly set up. The exact |
|
107 |
+commands depend on the SSH agent in use. |
|
108 |
+ |
|
109 |
+=== "OpenSSH" |
|
110 |
+ |
|
111 |
+ ~~~~ console title="Typical setup commands" |
|
112 |
+ $ # Start the agent. Also sets up the environment. |
|
113 |
+ $ eval `ssh-agent -s` |
|
114 |
+ Agent pid 12345 |
|
115 |
+ $ # Add your key, with a 900s timeout and requiring confirmation. |
|
116 |
+ $ ssh-add -t 900 -c ~/.ssh/my-vault-ed25519-key |
|
117 |
+ Enter passphrase for /home/user/.ssh/my-vault-ed25519-key (will confirm each use): |
|
118 |
+ Identity added: /home/user/.ssh/my-vault-ed25519-key (vault key) |
|
119 |
+ Lifetime set to 900 seconds |
|
120 |
+ The user must confirm each use of the key |
|
121 |
+ $ # The agent is ready to use. Don't forget to terminate the agent |
|
122 |
+ $ # when you're done: `kill 12345`, or whatever the agent pid is. |
|
123 |
+ ~~~~ |
|
124 |
+ |
|
125 |
+=== "PuTTY" |
|
126 |
+ |
|
127 |
+ ~~~~ console title="Typical setup commands" |
|
128 |
+ $ # Start the agent. Also sets up the environment and adds your key. |
|
129 |
+ $ eval `pageant -T ~/.ssh/my-vault-ed25519-key.ppk` |
|
130 |
+ Enter passphrase to load key 'vault key': |
|
131 |
+ $ # The agent is ready to use, and will persist until this console |
|
132 |
+ $ # is closed. |
|
133 |
+ ~~~~ |
|
134 |
+ |
|
135 |
+=== "GnuPG" |
|
136 |
+ |
|
137 |
+ `gpg-agent` is mainly intended to reuse OpenPGP keys in SSH |
|
138 |
+ contexts. Actually loading native SSH keys into `gpg-agent` |
|
139 |
+ requires a separate SSH agent client (such as OpenSSH). |
|
140 |
+ |
|
141 |
+ ~~~~ console title="Typical setup commands" |
|
142 |
+ $ # Enable SSH agent support in GnuPG; equivalent to passing |
|
143 |
+ $ # --enable-ssh-support upon agent startup. |
|
144 |
+ $ echo enable-ssh-support:0:1 | gpgconf --change-options gpg-agent |
|
145 |
+ $ # Add your key, requiring confirmation. Here we use the OpenSSH |
|
146 |
+ $ # tools. |
|
147 |
+ $ ssh-add -c ~/.ssh/my-vault-ed25519-key |
|
148 |
+ Enter passphrase for /home/user/.ssh/my-vault-ed25519-key (will confirm each use): |
|
149 |
+ Identity added: /home/user/.ssh/my-vault-ed25519-key (vault key) |
|
150 |
+ The user must confirm each use of the key |
|
151 |
+ $ # The agent is ready to use. |
|
152 |
+ ~~~~ |
|
153 |
+ |
|
154 |
+Next, configure `derivepassphrase vault` to use the loaded SSH key. (You |
|
155 |
+will be prompted to select the correct SSH key among the keys the agent |
|
156 |
+holds, unless there is only one suitable key.) |
|
157 |
+ |
|
158 |
+=== "global key" |
|
159 |
+ |
|
160 |
+ ~~~~ console |
|
161 |
+ $ derivepassphrase vault -k |
|
162 |
+ ~~~~ |
|
163 |
+ |
|
164 |
+ Now `derivepassphrase vault` will automatically use the configured |
|
165 |
+ key globally, even without the `-k`/`--key` option. |
|
166 |
+ |
|
167 |
+=== "key specifically for <var>SERVICE</var>" |
|
168 |
+ |
|
169 |
+ ~~~~ console |
|
170 |
+ $ derivepassphrase vault -k SERVICE |
|
171 |
+ ~~~~ |
|
172 |
+ |
|
173 |
+ Now `derivepassphrase vault` will automatically use the configured |
|
174 |
+ key for <var>SERVICE</var>, even without the `-k`/`--key` option. |
|
175 |
+ |
|
176 |
+[GnuPG]: https://gnupg.org/ |
|
177 |
+[ISSUE_WINDOWS_SUPPORT]: https://github.com/the-13th-letter/derivepassphrase/issues/13 |
|
178 |
+[OpenSSH]: https://www.openssh.com/ |
|
179 |
+[PuTTY]: https://www.chiark.greenend.org.uk/~sgtatham/putty/ |
|
180 |
+[PYTHON_AF_UNIX]: https://docs.python.org/3/library/socket.html#socket.AF_UNIX |
|
181 |
+[RFC 6979]: https://www.rfc-editor.org/rfc/rfc6979 |
... | ... |
@@ -94,7 +94,7 @@ We need to translate the passphrase policy into options for `derivepassphrase`: |
94 | 94 |
* A policy "between <var>n</var> and <var>m</var> characters long" translates to <code>-<span/>-length <var>k</var></code>, for any choice of <var>k</var> which satisfies <var>n</var> ≤ <var>k</var> ≤ <var>m</var>. |
95 | 95 |
(`derivepassphrase` does not explicitly choose <var>k</var> for you.) |
96 | 96 |
|
97 |
-??? note "Mnemonic: the `--repeat` option" |
|
97 |
+??? info "Mnemonic: the `--repeat` option" |
|
98 | 98 |
|
99 | 99 |
The `--repeat` option denotes the *total* number of consecutive occurrences of the same character. |
100 | 100 |
Or alternatively: if you request <code>-<span/>-repeat <var>n</var></code>, then `derivepassphrase` will *avoid* deriving any passphrase that repeats a character *another <var>n</var> times*. |
... | ... |
@@ -88,10 +88,10 @@ plugins: |
88 | 88 |
|
89 | 89 |
nav: |
90 | 90 |
- Overview: index.md |
91 |
- #- Tutorials & Examples: tutorials.md |
|
92 | 91 |
- Tutorials & Examples: |
93 | 92 |
- tutorials/basic-setup-passphrase.md |
94 |
- #- How-Tos: how-tos.md |
|
93 |
+ - How-Tos: |
|
94 |
+ - how-tos/ssh-key.md |
|
95 | 95 |
- Reference: |
96 | 96 |
- reference/index.md |
97 | 97 |
- 'Man page: derivepassphrase': reference/derivepassphrase.1.md |
98 | 98 |