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 |