Split the SSH key how-to into how-to and reference documents
Marco Ricci

Marco Ricci commited on 2024-11-26 00:32:29
Zeige 3 geänderte Dateien mit 284 Einfügungen und 128 Löschungen.


Because the original how-to discussed both prerequisites and the how-to
of SSH keys, it was tonally inconsistent.  It makes much more sense from
a reading flow perspective to move the discussion of prerequisites into
a separate reference document and link to it from the how-to page.  So
do exactly that.

Relative to the old how-to page, the new prerequisites reference page
additionally includes sections on how to determine the SSH key type from
the algorithm name used in the wire protocol, and sample transcripts for
generating new SSH keys suitable for `derivepassphrase vault`; this is
based on feedback for the old how-to page.  The new how-to page also
shows the actual key selection dialog instead of only the command-line
to run.
... ...
@@ -1,181 +1,118 @@
1 1
 # How to set up `derivepassphrase vault` with an SSH key
2 2
 
3
-## Prerequisites
4
-
5 3
 !!! abstract "See also"
6 4
 
7 5
     → Tradeoffs between a master passphrase and a master SSH key (TODO)
8 6
 
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**.
7
+## Prerequisites
8
+
9
+!!! abstract "Further reading"
10
+
11
+    → Full technical details: [Prerequisites for using `derivepassphrase
12
+    vault` with an SSH key][PREREQ]
13
+
14
+ 1. A running SSH agent; typically provided by OpenSSH or PuTTY.
15
+ 2. A Python installation that can talk to the SSH agent.
16
+ 3. A supported SSH key; typically an RSA, Ed25519 or Ed448 key.
101 17
 
102 18
 ## Configuring `derivepassphrase vault` to use an SSH key
103 19
 
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.
20
+Assuming the prerequisites are satisfied, ensure that the SSH agent is
21
+running, the SSH key is loaded into the agent, and the `SSH_AUTH_SOCK`
22
+environment variable is correctly set up.  The exact commands depend on
23
+the SSH agent in use.
108 24
 
109 25
 === "OpenSSH"
110 26
 
111
-    ~~~~ console title="Typical setup commands"
112
-    $ # Start the agent.  Also sets up the environment.
27
+    ~~~~ console title="Typical setup commands: starting the agent and setting up SSH_AUTH_SOCK"
113 28
     $ eval `ssh-agent -s`
114 29
     Agent pid 12345
115
-    $ # Add your key, with a 900s timeout and requiring confirmation.
30
+    ~~~~
31
+
32
+    (The process ID emitted above is helpful for signalling the agent
33
+    later, e.g. for termination.)
34
+
35
+    ~~~~ console title="Typical setup commands: loading the key into the agent, with 900s timeout and requiring confirmation"
116 36
     $ ssh-add -t 900 -c ~/.ssh/my-vault-ed25519-key
117 37
     Enter passphrase for /home/user/.ssh/my-vault-ed25519-key (will confirm each use): 
118 38
     Identity added: /home/user/.ssh/my-vault-ed25519-key (vault key)
119 39
     Lifetime set to 900 seconds
120 40
     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 41
     ~~~~
124 42
 
43
+    (Your key filename and key comment will likely differ.)
44
+
125 45
 === "PuTTY"
126 46
 
127
-    ~~~~ console title="Typical setup commands"
128
-    $ # Start the agent.  Also sets up the environment and adds your key.
47
+    ~~~~ console title="Typical setup commands: starting the agent and loading the key"
129 48
     $ eval `pageant -T ~/.ssh/my-vault-ed25519-key.ppk`
130 49
     Enter passphrase to load key 'vault key': 
131
-    $ # The agent is ready to use, and will persist until this console
132
-    $ # is closed.
133 50
     ~~~~
134 51
 
135
-=== "GnuPG"
52
+    (Your key filename and key comment will likely differ.  The agent
53
+    should automatically shut down once this terminal session is over.)
136 54
 
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).
55
+=== "GnuPG"
140 56
 
141
-    ~~~~ console title="Typical setup commands"
142
-    $ # Enable SSH agent support in GnuPG; equivalent to passing
143
-    $ # --enable-ssh-support upon agent startup.
57
+    ~~~~ console title="Typical setup commands: enabling SSH agent support in GnuPG"
58
+    $ # This is equivalent to passing --enable-ssh-support upon agent
59
+    $ # startup.
144 60
     $ echo enable-ssh-support:0:1 | gpgconf --change-options gpg-agent
145
-    $ # Add your key, requiring confirmation.  Here we use the OpenSSH
146
-    $ # tools.
61
+    ~~~~
62
+
63
+    (Loading native SSH keys into `gpg-agent` requires a separate SSH
64
+    agent client such as OpenSSH; see the [agent-specific notes in the
65
+    prerequisites][PREREQ_AGENT_SPECIFIC_NOTES].)
66
+
67
+    ~~~~ console title="Typical setup commands: loading the key into the agent with the OpenSSH tools"
147 68
     $ ssh-add -c ~/.ssh/my-vault-ed25519-key
148 69
     Enter passphrase for /home/user/.ssh/my-vault-ed25519-key (will confirm each use): 
149 70
     Identity added: /home/user/.ssh/my-vault-ed25519-key (vault key)
150 71
     The user must confirm each use of the key
151
-    $ # The agent is ready to use.
152 72
     ~~~~
153 73
 
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.)
74
+    (Your key filename and key comment may differ.)
75
+
76
+Next, configure `derivepassphrase vault` to use the loaded SSH key.
157 77
 
158 78
 === "global key"
159 79
 
160 80
     ~~~~ console
161
-    $ derivepassphrase vault -k
81
+    $ derivepassphrase vault --config -k
82
+    Suitable SSH keys:
83
+    [1] ssh-ed25519 ...n6tMofjJyWHLyjEXfXsJhBt+OuheHzPA/xRUqw  developer key
84
+    [2] ssh-rsa ...Cr5XE5ZbIjm1NYmxZ81G5IJkMgF3JTSE1PfQgbVHE=  my key comment
85
+    [3] ssh-ed25519 ...iimqEbE9kUM+G+g12hhuDNfsI/S02xtaphIOOH  vault key
86
+    Your selection? (1-3, leave empty to abort): 3
162 87
     ~~~~
163 88
 
89
+    (The prompt text will be "Use this key?" instead if there is only one
90
+    suitable key.)
91
+
164 92
     Now `derivepassphrase vault` will automatically use the configured
165 93
     key globally, even without the `-k`/`--key` option.
166 94
 
167 95
 === "key specifically for <var>SERVICE</var>"
168 96
 
169 97
     ~~~~ console
170
-    $ derivepassphrase vault -k SERVICE
98
+    $ derivepassphrase vault --config -k SERVICE
99
+    Suitable SSH keys:
100
+    [1] ssh-ed25519 ...n6tMofjJyWHLyjEXfXsJhBt+OuheHzPA/xRUqw  developer key
101
+    [2] ssh-rsa ...Cr5XE5ZbIjm1NYmxZ81G5IJkMgF3JTSE1PfQgbVHE=  my key comment
102
+    [3] ssh-ed25519 ...iimqEbE9kUM+G+g12hhuDNfsI/S02xtaphIOOH  vault key
103
+    Your selection? (1-3, leave empty to abort): 3
171 104
     ~~~~
172 105
 
106
+    (The prompt text will be "Use this key?" instead if there is only one
107
+    suitable key.)
108
+
173 109
     Now `derivepassphrase vault` will automatically use the configured
174 110
     key for <var>SERVICE</var>, even without the `-k`/`--key` option.
175 111
 
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
112
+!!! abstract "Further reading"
113
+
114
+    → Tradeoffs between a master passphrase and a master SSH key,
115
+    section "Should I use one master SSH key, or many keys?" (TODO)
116
+
117
+[PREREQ]: ../reference/prerequisites-ssh-key.md
118
+[PREREQ_AGENT_SPECIFIC_NOTES]: ../reference/prerequisites-ssh-key.md#agent-specific-notes
... ...
@@ -0,0 +1,217 @@
1
+# Prerequisites for using `derivepassphrase vault` with an SSH key
2
+
3
+Using `derivepassphrase vault` with an SSH key requires:
4
+
5
+ 1. [a running SSH agent](#ssh-agent),
6
+ 2. [a Python installation that can talk to the SSH
7
+    agent](#python-support), and
8
+ 3. [a supported SSH key.](#ssh-key)
9
+
10
+### A running SSH agent { #ssh-agent }
11
+
12
+SSH agents are usually packaged as part of SSH client distributions.
13
+`ssh-agent` from [OpenSSH][] and Pageant from [PuTTY][] are known to
14
+work. `gpg-agent` (v2) from [GnuPG][] is also known to work, but comes
15
+with caveats; see notes below.
16
+
17
+If in doubt, we recommend OpenSSH because it is the <i>de-facto</i>
18
+canonical SSH agent implementation.
19
+
20
+!!! note "Agent-specific features"
21
+
22
+    * OpenSSH's `ssh-agent` supports limiting the time the agent holds
23
+      the key in memory ("key lifetime").  We recommend its usage.
24
+    * `ssh-agent` and GnuPG's `gpg-agent` support requiring confirmation
25
+      upon each use for a specific key.  We recommend its usage as well.
26
+
27
+<section markdown id=agent-specific-notes>
28
+
29
+!!! note "Other agent-specific notes"
30
+
31
+    === "GnuPG/`gpg-agent`"
32
+
33
+        * `gpg-agent` v2.0 and later uses a *persistent* database of
34
+          known keys, SSH or otherwise.  "Adding" a key to the agent
35
+          actually means *importing* it, and requires choosing an
36
+          "import passphrase" to protect the key on disk, in the
37
+          persistent database.  `gpg-agent` will cache the import
38
+          passphrase in memory, and if that cache entry expires, then
39
+          the *import passphrase* must be provided to unlock the key.
40
+
41
+        * The GnuPG distribution does not contain tools to generate
42
+          native SSH keys or interactively add keys to a running
43
+          `gpg-agent`, because its purpose is to expose keys in
44
+          a different format (OpenPGP) to other (agent-compatible) SSH
45
+          clients.  A third-party tool (such as a full SSH client
46
+          distribution) is necessary to load/import native SSH keys into
47
+          `gpg-agent`.
48
+
49
+        * As a design consequence of the persistent database,
50
+          `gpg-agent` always lists all known SSH keys as available in
51
+          the agent.  It is impossible to remove an SSH key from
52
+          `gpg-agent` using standard SSH agent operations.
53
+
54
+        * `gpg-agent` does not advertise its communication socket by
55
+          default, contrary to other SSH agents, so it must be manually
56
+          advertised:
57
+
58
+            ~~~~ console
59
+            $ SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
60
+            $ export SSH_AUTH_SOCK
61
+            ~~~~
62
+
63
+</section>
64
+
65
+### A Python installation that can talk to the SSH agent { #python-support }
66
+
67
+!!! bug "Windows is currently *not* supported"
68
+
69
+    <i>→ Further details:</i> [Issue
70
+    `the-13th-letter/derivepassphrase#13`: Support PuTTY/Pageant on
71
+    Windows][ISSUE_WINDOWS_SUPPORT]
72
+
73
+    The two major SSH agents on Windows (PuTTY/Pageant and OpenSSH) use
74
+    <i>Windows named pipes</i> for communication, and Python on Windows
75
+    does not inherently support named pipes.  Since no comprehensive
76
+    third-party Python modules to interface with named pipes appear to
77
+    exist, teaching `derivepassphrase` to use Windows named pipes
78
+    will require us developers to write a custom low-level C module
79
+    specific to this application---an unrealistic task if we lack both
80
+    technical know-how for the named pipe API as well as Windows
81
+    hardware to test any potential implementation on.
82
+
83
+On non-Windows operating systems, the SSH agent is expected to advertise
84
+its communication socket via the `SSH_AUTH_SOCK` environment variable,
85
+which is common procedure.  Therefore, [your Python installation must
86
+support UNIX domain sockets][socket.AF_UNIX].
87
+
88
+### A supported SSH key { #ssh-key }
89
+
90
+For an SSH key to be usable by `derivepassphrase`, the SSH agent must
91
+always generate the same signature for the same input, i.e. the
92
+signature must be deterministic for this key type.  Commonly used SSH
93
+key types include [RSA][], [DSA][], [ECDSA][], [Ed25519][] and
94
+[Ed448][].
95
+
96
+  [RSA]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)
97
+  [DSA]: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
98
+  [ECDSA]: https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm
99
+  [Ed25519]: https://en.wikipedia.org/wiki/EdDSA#Ed25519
100
+  [Ed448]: https://en.wikipedia.org/wiki/EdDSA#Ed448
101
+
102
+* RSA, Ed25519 and Ed448 signatures are deterministic by definition.
103
+  Thus RSA, Ed25519 and Ed448 keys are supported under any SSH agent
104
+  that implements them.
105
+
106
+* DSA and ECDSA signatures require choosing a value specific to each
107
+  signature (a "cryptographic nonce"), which must be unpredictable.
108
+  Typical DSA/ECDSA implementations therefore generate a suitably large
109
+  random number as the nonce.  This makes signatures non-deterministic,
110
+  and thus unsuitable for `derivepassphrase`.
111
+
112
+    ??? info "Exception: PuTTY/Pageant and RFC 6979"
113
+
114
+        [RFC 6979][] specifies a method to *calculate* the nonce from
115
+        the DSA/ECDSA key and the message to be signed.  DSA/ECDSA
116
+        signatures from SSH agents implementing RFC 6979 are therefore
117
+        deterministic, and thus *also* suitable for `derivepassphrase`.
118
+        Pageant 0.81 implements RFC 6979.
119
+
120
+        !!! warning "Warning: Pageant < 0.81"
121
+
122
+            Pageant 0.80 and earlier uses a different, homegrown method
123
+            to calculate the nonce deterministically.  Those versions
124
+            are *also* prinicipally suitable for use with
125
+            `derivepassphrase`, but **they generate different signatures
126
+            -- and different derived passphrases -- than Pageant 0.81
127
+            and later**.
128
+
129
+??? info "What SSH key type do I have?"
130
+
131
+    If, according to your SSH agent, your key's type…
132
+
133
+      * …ends with `-cert-v01@openssh.com`, then, for the purposes of
134
+        this list, ignore the `-cert-v01@openssh.com` suffix.
135
+      * …is `dsa` or `ssh-dss`, or is `dsa` followed by a number, then
136
+        your key type is **DSA**.
137
+      * …is `rsa` or `ssh-rsa`, or is `rsa` followed by a number, then
138
+        your key type is **RSA**.
139
+      * …is `ecdsa` followed by a number, or is `ecdsa-sha2-nistp`
140
+        followed by a number, then your key type is **ECDSA**.
141
+      * …is `ssh-ed25519`, then your key type is **Ed25519**.
142
+      * …is `ssh-ed448`, then your key type is **Ed448**.
143
+
144
+If you do not yet have a (supported) SSH key, we recommend Ed25519 for
145
+maximum speed and reasonable availability, otherwise RSA for maximum
146
+availability.  We do not in general recommend Ed448 because it is not
147
+widely implemented.
148
+
149
+??? example "Generating new SSH keys for `derivepassphrase`"
150
+
151
+    === "OpenSSH"
152
+
153
+        The resulting key will be stored in
154
+        `~/.ssh/my-vault-ed25519-key`, using "vault key" as a comment.
155
+        Replace `-t ed25519` with `-t rsa` if generating an RSA key, and
156
+        adapt the filename accordingly.
157
+
158
+        ~~~~ console
159
+        $ ssh-keygen -t ed25519 -f ~/.ssh/my-vault-ed25519-key -C "vault key"
160
+        Generating public/private ed25519 key pair.
161
+        Enter passphrase for ".../.ssh/my-vault-ed25519-key" (empty for no passphrase): 
162
+        Enter same passphrase again:
163
+        Your identification has been saved in .../.ssh/my-vault-ed25519-key
164
+        Your public key has been saved in .../.ssh/my-vault-ed25519-key.pub
165
+        The key fingerprint is:
166
+        SHA256:BKD43lBB7qh4VvZxq6xSYDXUUbXF6snrRF7qUnOx1PA vault key
167
+        The key's randomart image is:
168
+        +--[ED25519 256]--+
169
+        |   o=ooo.....    |
170
+        | . oo...   oo    |
171
+        |. ..o.  . .. +   |
172
+        | .o+   .  . o E  |
173
+        | .+.+ . So.o.o   |
174
+        |.o =.. o +*oo    |
175
+        |o +.. . ..++     |
176
+        | o.  . ..o.      |
177
+        |   ...o  oo      |
178
+        +----[SHA256]-----+
179
+        ~~~~
180
+
181
+        (The key fingerprint and the randomart image will naturally
182
+        differ, as they are key-specific.)
183
+
184
+    === "PuTTY"
185
+
186
+        The resulting key will be stored in
187
+        `~/.ssh/my-vault-ed25519-key.ppk`, using "vault key" as a comment.
188
+        Replace `-t ed25519` with `-t rsa` if generating an RSA key, and
189
+        adapt the filename accordingly.
190
+
191
+        ~~~~ console
192
+        $ puttygen -t ed25519 -o ~/.ssh/my-vault-ed25519-key.ppk -C "vault key"
193
+        Enter passphrase to save key: 
194
+        Re-enter passphrase to verify: 
195
+        ~~~~
196
+
197
+    === "GnuPG"
198
+
199
+        Not supported natively.  An alternative SSH client distribution
200
+        such as OpenSSH or PuTTY is necessary
201
+
202
+        Alternatively, GnuPG supports reusing keys in its native OpenPGP
203
+        format for SSH as long as the underlying key type is compatible.
204
+
205
+---
206
+
207
+!!! abstract "Further reading"
208
+
209
+    → [How to set up `derivepassphrase vault` with an SSH key][HOWTO]
210
+
211
+[HOWTO]: ../how-tos/ssh-key.md
212
+[GnuPG]: https://gnupg.org/
213
+[ISSUE_WINDOWS_SUPPORT]: https://github.com/the-13th-letter/derivepassphrase/issues/13
214
+[OpenSSH]: https://www.openssh.com/
215
+[PuTTY]: https://www.chiark.greenend.org.uk/~sgtatham/putty/
216
+[PYTHON_AF_UNIX]: https://docs.python.org/3/library/socket.html#socket.AF_UNIX
217
+[RFC 6979]: https://www.rfc-editor.org/rfc/rfc6979
... ...
@@ -105,6 +105,8 @@ nav:
105 105
       - Submodule ssh_agent: reference/derivepassphrase.ssh_agent.md
106 106
       - Submodule _types: reference/derivepassphrase._types.md
107 107
       - Submodule vault: reference/derivepassphrase.vault.md
108
+    - Prerequisites:
109
+      - 'Using derivepassphrase vault with an SSH key': reference/prerequisites-ssh-key.md
108 110
   #- Design & Background: explanation.md
109 111
   - Changelog: changelog.md
110 112
 exclude_docs: |
111 113