Update the documentation on SSH agent support on Windows
Marco Ricci

Marco Ricci commited on 2025-12-25 23:37:49
Zeige 2 geänderte Dateien mit 129 Einfügungen und 29 Löschungen.


The how-to "How to set up derivepassphrase vault with an SSH key" and
the reference documentation "Prerequisites for using derivepassphrase
vault with an SSH key" include new sections on Pageant and OpenSSH on
Windows.  For the latter, the "prerequisites" document also includes
information on the deficiencies of the Windows port of OpenSSH, i.e.,
that the connection is aborted upon receiving unsupported requests (in
violation of the communication protocol) and that the port lacks the
features which normally distinguish OpenSSH from Pageant.

We also expand the section on GnuPG's OpenSSH emulation on Windows in
the "prerequisites" document: that the mode is untested because the
documentation is wrong, and that we're now waiting for feedback from the
GnuPG developers.
... ...
@@ -18,12 +18,14 @@
18 18
 ## Configuring `derivepassphrase vault` to use an SSH key
19 19
 
20 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.
21
+running, the SSH key is loaded into the agent, and, on UNIX systems,
22
+that the `SSH_AUTH_SOCK` environment variable is correctly set up.
23 23
 The exact commands depend on the SSH agent in use.
24 24
 
25 25
 === "OpenSSH"
26 26
 
27
+    === "on UNIX"
28
+
27 29
         ~~~~ console title="Typical setup commands: starting the agent and setting up SSH_AUTH_SOCK"
28 30
         $ eval `ssh-agent -s`
29 31
         Agent pid 12345
... ...
@@ -42,29 +44,95 @@ The exact commands depend on the SSH agent in use.
42 44
 
43 45
         (Your key filename and key comment will likely differ.)
44 46
 
47
+    === "on Windows"
48
+
49
+        ([Using OpenSSH on Windows is possible, but currently *not
50
+        recommended*; we recommend Pageant
51
+        instead.][OPENSSH_ON_WINDOWS_LIMITATIONS]
52
+        Pageant has priority over OpenSSH: if both are running,
53
+        `derivepassphrase vault` will connect to Pageant.)
54
+
55
+        The agent is started as a system service.
56
+        This only needs to be set up once.
57
+
58
+        <small>([Source: OpenSSH-on-Windows
59
+        documentation][OPENSSH_ON_WINDOWS_DOC].)</small>
60
+
61
+        ~~~~ pwsh-session title="Typical setup commands (PowerShell, as Administrator): starting the agent"
62
+        PS> Get-Service ssh-agent | Set-Service -StartupType Automatic
63
+        PS> Start-Service ssh-agent
64
+        ~~~~
65
+
66
+        Load the keys into the agent.
67
+        This only needs to be done once.
68
+        The agent stores the key material in a reusable, per-user
69
+        Windows security context.
70
+        Unlike on UNIX, the Windows port of OpenSSH does not support key
71
+        timeouts or key usage confirmation prompts.
72
+
73
+        ~~~~ pwsh-session title="Further setup commands (Powershell, as User): loading the key into the agent"
74
+        PS> ssh-add "C:\Users\YourUsernameHere\Documents\my-vault-ed25519-key"
75
+        Enter passphrase for C:\Users\YourUsernameHere\Documents\my-vault-ed25519-key:
76
+        Identity added: C:\Users\YourUsernameHere\Documents\my-vault-ed25519-key (vault key)
77
+        ~~~~
78
+
79
+        (Your key filename and key comment will likely differ.)
80
+
81
+        [OPENSSH_ON_WINDOWS_LIMITATIONS]: ../reference/prerequisites-ssh-key.md#agent-specific-notes
82
+        [OPENSSH_ON_WINDOWS_DOC]: https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement#user-key-generation
83
+
45 84
 === "PuTTY"
46 85
 
86
+    === "on Windows"
87
+
88
+        Start Pageant; this adds the Pageant icon to the Windows task
89
+        bar.
90
+        Then add the key via the right-click context menu, "Add key" or
91
+        "Add key (encrypted)".
92
+
93
+        Adding the key via "Add key (encrypted)" makes the key material
94
+        manually "lockable" and "unlockable" by decrypting and
95
+        re-encrypting it, meaning that the key cannot be used by
96
+        malicious clients while encrypted.
97
+        This can be used to partially alleviate the lack of support for
98
+        the "key timeout" constraint.
99
+        The "Add key (encrypted)" mode is thus *recommended*.
100
+
101
+    === "on UNIX"
102
+
47 103
         ~~~~ console title="Typical setup commands: starting the agent and loading the key"
48 104
         $ eval `pageant -T ~/.ssh/my-vault-ed25519-key.ppk`
49 105
         Enter passphrase to load key 'vault key': 
50 106
         ~~~~
51 107
 
52 108
         (Your key filename and key comment will likely differ.
53
-    The agent should automatically shut down once this terminal session
54
-    is over.)
109
+        The agent should automatically shut down once this terminal
110
+        session is over.)
55 111
 
56 112
 === "GnuPG"
57 113
 
114
+    === "on UNIX"
115
+
58 116
         ~~~~ console title="Typical setup commands: enabling SSH agent support in GnuPG"
59 117
         $ # This is equivalent to passing --enable-ssh-support upon agent
60 118
         $ # startup.
61 119
         $ echo enable-ssh-support:0:1 | gpgconf --change-options gpg-agent
62 120
         ~~~~
63 121
 
122
+    === "on Windows"
123
+
124
+        ~~~~ pwsh-session title="Typical setup commands (PowerShell): enabling SSH agent support in GnuPG"
125
+        PS> # This is equivalent to passing --enable-ssh-support upon agent
126
+        PS> # startup.
127
+        PS> echo enable-ssh-support:0:1 | gpgconf --change-options gpg-agent
128
+        ~~~~
129
+
64 130
     (Loading native SSH keys into `gpg-agent` requires a separate SSH
65 131
     agent client such as OpenSSH; see the [agent-specific notes in the
66 132
     prerequisites][PREREQ_AGENT_SPECIFIC_NOTES].)
67 133
 
134
+    === "on UNIX"
135
+
68 136
         ~~~~ console title="Typical setup commands: loading the key into the agent with the OpenSSH tools"
69 137
         $ ssh-add -c ~/.ssh/my-vault-ed25519-key
70 138
         Enter passphrase for /home/user/.ssh/my-vault-ed25519-key (will confirm each use): 
... ...
@@ -72,6 +140,15 @@ The exact commands depend on the SSH agent in use.
72 140
         The user must confirm each use of the key
73 141
         ~~~~
74 142
 
143
+    === "on Windows"
144
+
145
+        ~~~~ console title="Typical setup commands (PowerShell): loading the key into the agent with the OpenSSH tools"
146
+        $ ssh-add "C:\Users\YourUsernameHere\Documents\my-vault-ed25519-key"
147
+        Enter passphrase for C:\Users\YourUsernameHere\Documents\my-vault-ed25519-key (will confirm each use): 
148
+        Identity added: C:\Users\YourUsernameHere\Documents\my-vault-ed25519-key (vault key)
149
+        The user must confirm each use of the key
150
+        ~~~~
151
+
75 152
     (Your key filename and key comment may differ.)
76 153
 
77 154
 Next, configure `derivepassphrase vault` to use the loaded SSH key.
... ...
@@ -10,27 +10,57 @@ Using `derivepassphrase vault` with an SSH key requires:
10 10
 ### A running SSH agent { #ssh-agent }
11 11
 
12 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.
13
+Pageant from [PuTTY][] is known to work, on both UNIX and Windows.
14
+`ssh-agent` from [OpenSSH][] is known to work well on UNIX, and
15
+somewhat poorly on Windows; see notes below.
15 16
 `gpg-agent` (v2) from [GnuPG][] is also known to work, but comes with
16
-caveats; see notes below.
17
+caveats; again, see notes below.
17 18
 
18
-If in doubt, we recommend OpenSSH because it is the <i>de-facto</i>
19
-canonical SSH agent implementation.
19
+If in doubt, we recommend OpenSSH on UNIX and Pageant on Windows,
20
+because they are the <i>de-facto</i> canonical SSH agent implementation
21
+on their respective operating system.
20 22
 
21 23
 !!! note "Agent-specific features"
22 24
 
23 25
     * OpenSSH's `ssh-agent` supports limiting the time the agent holds
24
-      the key in memory ("key lifetime").
26
+      the key in memory ("key lifetime"), on UNIX only.
25 27
       We recommend its usage.
26 28
     * `ssh-agent` and GnuPG's `gpg-agent` support requiring confirmation
27 29
       upon each use for a specific key.
30
+      (Again, for `ssh-agent` only on UNIX.)
28 31
       We recommend its usage as well.
29 32
 
30 33
 <section markdown id=agent-specific-notes>
31 34
 
32 35
 !!! note "Other agent-specific notes"
33 36
 
37
+    === "OpenSSH on Windows"
38
+
39
+        Using OpenSSH on Windows with `derivepassphrase vault` is
40
+        possible, but currently *not recommended*.
41
+        [The Windows port of OpenSSH lacks support for key constraints
42
+        [1]][OPENSSH_ON_WINDOWS_NO_KEY_CONSTRAINTS_1]
43
+        [[2]][OPENSSH_ON_WINDOWS_NO_KEY_CONSTRAINTS_2], which are the
44
+        main advantage OpenSSH had over Pageant.
45
+        Without this functionality, Pageant is the better choice: more
46
+        supported key formats, manually lockable and unlockable key
47
+        material in the agent, and no Administrator credentials needed
48
+        to configure the system.
49
+
50
+        Additionally, the ported SSH agent implements the agent
51
+        protocol incorrectly because it terminates the connection when
52
+        encountering an unsupported request, instead of returning an
53
+        error code.
54
+        (The original agent, on UNIX, implements the protocol
55
+        correctly.)
56
+        This makes it difficult for `derivepassphrase vault` to
57
+        correctly *detect* or *verify* that it is talking to the
58
+        OpenSSH agent on Windows, instead of merely *assuming* it is
59
+        doing so.
60
+
61
+        [OPENSSH_ON_WINDOWS_NO_KEY_CONSTRAINTS_1]: https://github.com/PowerShell/Win32-OpenSSH/issues/1056#issuecomment-362494167 "Issue #1056: ssh-agent should support '-c' and '-t' options of ssh-add"
62
+        [OPENSSH_ON_WINDOWS_NO_KEY_CONSTRAINTS_2]: https://github.com/PowerShell/Win32-OpenSSH/issues/2314#issuecomment-2529160589 'Issue #2314: Adding key with confirmation option to ssh-agent gives "agent refused operation"'
63
+
34 64
     === "GnuPG/`gpg-agent`"
35 65
 
36 66
         * `gpg-agent` v2.0 and later uses a *persistent* database of
... ...
@@ -97,30 +127,23 @@ canonical SSH agent implementation.
97 127
                 configuration file instead of being manually supplied on
98 128
                 the command-line.)
99 129
 
100
-                [This mode, sadly, is not currently
101
-                supported.](#python-support)
130
+                This mode is untested.
131
+                We, the `derivepassphrase` authors, do not know how to
132
+                run `gpg-agent` on Windows with masquerading as OpenSSH
133
+                enabled: the steps outlined in the official
134
+                documentation for `gpg-agent` do not work as advertised.
135
+                [We have asked for clarification on GnuPG's developer
136
+                mailing list.][GPG_AGENT_ON_WINDOWS_WTF]
137
+
138
+                [GPG_AGENT_ON_WINDOWS_WTF]: https://lists.gnupg.org/pipermail/gnupg-devel/2025-December/036116.html
102 139
 
103 140
 </section>
104 141
 
105 142
 ### A Python installation that can talk to the SSH agent { #python-support }
106 143
 
107
-!!! bug "Windows is currently *not* supported"
108
-
109
-    <i>→ Bug entry:</i> [Support PuTTY/Pageant (and maybe
110
-    OpenSSH/`ssh-agent`) on Windows][BUG_WINDOWS_SSH_AGENT_SUPPORT]
111
-
112
-    The two major SSH agents on Windows (PuTTY/Pageant and OpenSSH) use
113
-    <i>Windows named pipes</i> for communication, and Python on Windows
114
-    does not inherently support named pipes.
115
-    Since no comprehensive third-party Python modules to interface with
116
-    named pipes appear to exist, teaching `derivepassphrase` to use
117
-    Windows named pipes requires us developers to write the code to
118
-    interface the Windows system libraries ourselves.
119
-    Development on this started after the release of version 0.5, but
120
-    since this is not our area of expertise, and because the pre-0.5
121
-    design hard-codes the UNIX style of looking up and connecting to an
122
-    SSH agent, development progress on this front has been much slower
123
-    than usual.
144
+As of version 0.6, Windows is supported.
145
+[Your Python installation must support interfacing with the Windows
146
+system DLLs.][ctypes.WinDLL]
124 147
 
125 148
 On non-Windows operating systems, the SSH agent is expected to advertise
126 149
 its communication socket via the `SSH_AUTH_SOCK` environment variable,
127 150