Split the SSH key how-to in...
Marco Ricci authored 3 weeks ago
|
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:
|