RFC 9987
Secure Shell (SSH) Agent Protocol
RFC 9987: Secure Shell (SSH) Agent Protocol ๐ฆ
- Request for Comments: 9987 ๐
- Author: D. Miller, OpenSSH ๐ฉโ๐ป
- Category: Standards Track โ
- Date: May 2026 ๐
- ISSN: 2070-1721
- Stream: Internet Engineering Task Force (IETF)
- Obsoletes / Updates: this copy's header doesn't list either one, so there's nothing to obsolete or update here ๐คทโโ๏ธ
Abstract ๐
okay so this doc specs a key agent protocol for use in the Secure Shell (SSH) protocol ๐. that's the whole vibe โจ.
Status of This Memo ๐
This is an Internet Standards Track document. ๐
This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841.
Info about the current status of this document, any errata, and how to send feedback is at https://www.rfc-editor.org/info/rfc9987 ๐.
Copyright Notice ยฉ๏ธ
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License ๐.
Table of Contents ๐๏ธ
1. Introduction
2. Requirements Language
3. Protocol Overview
4. Terminology and Units
5. Protocol Messages
5.1. Generic Agent Responses
5.2. Adding Keys to the Agent
5.2.1. DSA Keys
5.2.2. ECDSA Keys
5.2.3. EdDSA Keys
5.2.4. RSA Keys
5.2.5. Other Keys
5.2.6. Adding Keys from a Token
5.2.7. Key Constraints
5.3. Public Key Encoding
5.4. Removing Keys from the Agent
5.5. Requesting a List of Keys
5.6. Private Key Operations
5.6.1. Signature Flags
5.7. Locking and Unlocking an Agent
5.8. Extension Mechanism
5.8.1. Query Extension
6. Connecting to an Agent
7. Forwarding Access to an Agent
7.1. Advertising Agent Forwarding Support
7.2. Requesting Agent Forwarding
7.3. Agent Connection Requests
8. Protocol Numbers
8.1. Message Type Numbers
8.1.1. Reserved Message Type Numbers
8.2. Constraint Identifiers
8.3. Signature Flags
9. IANA Considerations
9.1. Guidance for Designated Experts
9.2. "SSH Agent Protocol Message Type Numbers" Registry
9.3. "SSH Agent Key Constraint Numbers" Registry
9.4. "SSH Agent Key Constraint Extension Names" Registry
9.5. "SSH Agent Signature Flags" Registry
9.6. "SSH Agent Extension Request Names" Registry
9.7. Additions to the "Extension Names" Registry
9.8. Additions to the "Connection Protocol Channel Request
Names" Registry
9.9. Additions to the "Connection Protocol Channel Types"
Registry
10. Security Considerations
11. References
11.1. Normative References
11.2. Informative References
Acknowledgments
Author's Address
1. Introduction โจ
okay so SSH [RFC4251] is a protocol for secure remote connections [RFC4253] and login [RFC4254] over untrusted networks ๐. It supports multiple authentication mechanisms [RFC4252], including public key authentication ๐. This document specifies the protocol for talking to a key management component that everyone calls "an agent", the one holding the private keys ๐๏ธ. SSH clients (and possibly SSH servers) can ping the agent through this protocol to do operations with the public and private keys sitting inside it ๐ .
Holding keys in an agent is a whole usability and security glow-up compared to loading and unwrapping them at every single use, since each unwrap can mean typing in a passphrase ๐. Access to an agent may optionally be forwarded across an SSH connection, so remote systems can use stored keys without the key material ever being directly exposed to them ๐ง. And the agent can be its own dedicated component with a smaller attack surface than a key loaded into a full SSH server or client, and it may get special protection from the wider system ๐ก๏ธ.
2. Requirements Language ๐
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be read as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in all capitals, just like here ๐.
3. Protocol Overview ๐ธ
The agent protocol is a packetised request-response protocol, and the client is the only one driving it ๐ฌ. The client sends a bunch of requests to an agent, and the agent sends back a set of reply messages in response. The agent never sends anything unless a client asked first ๐ โโ๏ธ. Replies come back in order ๐ฌ.
These requests cover loading keys into an agent, removing some or all keys from an agent, and running signature operations with keys that were loaded earlier ๐๏ธ.
Agents MAY implement support for only a subset of the available key types, and they MAY additionally refuse some operations in particular contexts. For example, an agent might only let clients local to itself add keys, or it might show particular subsets of keys to a given client ๐. For this reason, clients of the agent SHOULD be ready to fail gracefully whenever an operation gets refused ๐ซถ.
4. Terminology and Units ๐ง
From here on, "agent" means the key management component that implements the responder side of this protocol ๐ค. "Client" means a tool that implements the requester side and talks to an agent ๐ฑ. If it matters that the client is a Secure Shell client as described in [RFC4251], it gets called an "SSH client". Similarly, "SSH server" refers to Secure Shell servers ๐ฅ๏ธ.
All encoding data types ("byte", "uint32", "string", etc.) are as specified in Section 5 of [RFC4251]. There's also byte[], which without a length in the square brackets just means an unadorned sequence of zero or more bytes, where the length is decided by context ๐งฉ.
All length units are given in bytes unless otherwise specified ๐.
5. Protocol Messages ๐จ
Messages are made of a "length", a "type", and "contents" ๐:
uint32 length
byte type
byte[length - 1] contents
In the sections below, the "length" field gets left out. For clarity, the symbolic names of the message types are shown, and their numeric values are listed in Section 8.1 ๐ข.
5.1. Generic Agent Responses ๐
The following generic messages can come back from the agent in response to client requests. On success, the agent MUST reply either with the single-byte response:
byte SSH_AGENT_SUCCESS
or with a request-specific success message that may contain additional fields. On failure, the agent MUST reply with the single-byte response:
byte SSH_AGENT_FAILURE
or with a request-specific failure message that may contain additional fields. SSH_AGENT_FAILURE messages MUST also be sent in reply to requests with unknown or unsupported types ๐.
5.2. Adding Keys to the Agent ๐
Keys can be added to the agent using the SSH_AGENTC_ADD_IDENTITY or SSH_AGENTC_ADD_ID_CONSTRAINED messages. The latter variant lets you add keys with optional constraints on how they get used ๐.
The generic format for the SSH_AGENTC_ADD_IDENTITY message is:
byte SSH_AGENTC_ADD_IDENTITY
string key type
byte[] key data
string comment
So "key type" is the specified key type name, like "ssh-rsa" for an RSA key as defined by [RFC4253]. The "key data" holds the public and private components of the key, and it changes depending on the key type, as laid out in Sections 5.2.1 through 5.2.4 for commonly used key types ๐ง. A "comment" is a human-readable key name or comment as a UTF-8 string, and it can help identify the key in user-visible messages ๐ฌ. This string is allowed to be zero length.
The SSH_AGENTC_ADD_ID_CONSTRAINED message is basically the same but adds one extra field:
byte SSH_AGENTC_ADD_ID_CONSTRAINED
string key type
byte[] key data
string comment
constraint[] constraints
Constraints put limits on how valid or usable a key is. Section 5.2.7 goes through the constraint types and their formats ๐. Clients SHOULD prefer the SSH_AGENTC_ADD_IDENTITY message over sending an SSH_AGENTC_ADD_ID_CONSTRAINED message with an empty "constraints" field, even though both are valid and equivalent โจ.
An agent MUST reply with SSH_AGENT_SUCCESS if the key was successfully loaded as a result of one of these messages, or SSH_AGENT_FAILURE otherwise ๐.
Adding a key that's already in an agent SHOULD replace any constraints it was loaded with before with the ones (if any) present in the new add request. This way, security-relevant constraints on a loaded key match what the user expects, which is so important ๐ฅน. Otherwise, an agent MAY refuse to load a key that has already been loaded ๐ โโ๏ธ.
An agent MAY support only a subset of the key types defined here, and it MAY support additional key types as described below. If an agent doesn't recognise the type name in a request to add a key, then it MUST respond with an SSH_AGENT_FAILURE reply ๐.
5.2.1. DSA Keys ๐
Digital Signature Algorithm (DSA) keys have the key type name "ssh-dss" and are defined in [RFC4253]. They may be added to the agent using the following message. The "constraints" field is only present for the SSH_AGENTC_ADD_ID_CONSTRAINED message ๐งพ.
byte SSH_AGENTC_ADD_IDENTITY or
SSH_AGENTC_ADD_ID_CONSTRAINED
string "ssh-dss"
mpint p
mpint q
mpint g
mpint y
mpint x
string comment
constraint[] constraints
The "p", "q", and "g" values are the DSA domain parameters. The "y" and "x" values are the public and private keys, respectively. These values are as defined by Section 4.1 of [FIPS.186-4] ๐งฎ.
5.2.2. ECDSA Keys ๐
Elliptic Curve Digital Signature Algorithm (ECDSA) keys have key types that start with "ecdsa-sha2-" and are defined in [RFC5656]. They may be added to the agent using the following message. The "constraints" field is only present for the SSH_AGENTC_ADD_ID_CONSTRAINED message ๐ฆ.
byte SSH_AGENTC_ADD_IDENTITY or
SSH_AGENTC_ADD_ID_CONSTRAINED
string key type
string ecdsa_curve_name
string Q
mpint d
string comment
constraint[] constraints
The values "Q" and "d" are the ECDSA public and private values, respectively. Both are defined by Section 6.2 of [FIPS.186-5] ๐.
5.2.3. EdDSA Keys
okay bestie, EdDSA keys are giving clean elegance ๐ฆโจ [RFC8709] defines Edwards-curve Digital Signature Algorithm (EdDSA) keys (see [RFC8032]) Ed25519 and Ed448 with key type names "ssh-ed25519" and "ssh-ed448", respectively. These can be added to the agent with the following message. The constraints field only shows up in the SSH_AGENTC_ADD_ID_CONSTRAINED message ๐
byte SSH_AGENTC_ADD_IDENTITY or
SSH_AGENTC_ADD_ID_CONSTRAINED
string "ssh-ed25519" or "ssh-ed448"
string ENC(A)
string k || ENC(A)
string comment
constraint[] constraints
The first value is the EdDSA public key ENC(A) ๐ The second value is the private key k joined with the public ENC(A) key. Yes, the public key gets repeated on purpose, so it stays compatible with the widely deployed implementations ๐ซถ The contents and interpretation of the ENC(A) and k values are defined by Section 3.2 of [RFC8032] ๐
5.2.4. RSA Keys
RSA keys have the key type name "ssh-rsa" and they're defined in [RFC4253] ๐ They can be added to the agent with the following message. The constraints field only appears in the SSH_AGENTC_ADD_ID_CONSTRAINED message ๐
byte SSH_AGENTC_ADD_IDENTITY or
SSH_AGENTC_ADD_ID_CONSTRAINED
string "ssh-rsa"
mpint n
mpint e
mpint d
mpint iqmp
mpint p
mpint q
string comment
constraint[] constraints
n is the public composite modulus. e is the public exponent. d is the private exponent. p and q are its constituent private prime factors. iqmp is the inverse of q modulo p. All of these values, except iqmp (which can be calculated from the others), are defined by Section 5.1 of [FIPS.186-5] ๐ฅ
5.2.5. Other Keys
Agents and their clients MAY support additional key types that aren't documented here ๐ธ Vendor-specific key types MUST use the domain-qualified naming convention from Section 6 of [RFC4251] until IANA allocates codepoints for them [IANA-PUBKEYS] ๐ง
5.2.6. Adding Keys from a Token
Keys hosted on smart-cards or other hardware tokens can be added using the SSH_AGENTC_ADD_SMARTCARD_KEY and SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests. Heads up, the constraints field is only included in the SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED version of this message ๐
byte SSH_AGENTC_ADD_SMARTCARD_KEY or
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
string token id
string PIN
constraint[] constraints
Here token id is an opaque identifier for the hardware token, and PIN is an optional password or PIN to unlock the key. The protocol doesn't define how token id gets interpreted. That's left totally up to the agent ๐
Typically, only the public components of any keys on a hardware token get loaded into an agent. So, strictly speaking, this message really sets things up so future private key operations get delegated to that hardware token. Main character energy for the token ๐
An agent MUST reply with SSH_AGENT_SUCCESS if one or more keys were loaded successfully as a result of one of these messages. It MUST reply with SSH_AGENT_FAILURE if no keys were found. The agent MUST also return SSH_AGENT_FAILURE if the token id wasn't recognised, if the request went against agent policy, or if the agent doesn't support token-hosted keys at all ๐
5.2.7. Key Constraints
A bunch of constraints can be used in the constrained variants of the key add messages โจ Each constraint is represented by a type byte followed by zero or more value bytes.
Zero or more constraints can be specified when you add a key with one of the *_CONSTRAINED requests. Multiple constraints get appended one after another to the end of the request:
byte constraint1_type
byte[] constraint1_data
byte constraint2_type
byte[] constraint2_data
....
byte constraintN_type
byte[] constraintN_data
To fully parse a constraint, you have to know its structure beforehand. It's not possible to safely recover when you hit an unrecognised constraint. Given this, if an agent does not recognise or support a requested constraint, it MUST abort parsing, refuse the request, and return an SSH_AGENT_FAILURE message to the client ๐ซ๐
The following subsections describe the constraints that have been defined ๐
5.2.7.1. Key Lifetime Constraint
This constraint asks the agent to limit the key's lifetime by deleting it once the specified duration (in seconds) has passed since the key was added to the agent โณ
byte SSH_AGENT_CONSTRAIN_LIFETIME
uint32 seconds
5.2.7.2. Key Confirmation Constraint
This constraint asks the agent to require explicit user confirmation for each private key operation that uses the key. For example, the agent could show a confirmation dialog before completing a signature operation ๐โโ๏ธ
byte SSH_AGENT_CONSTRAIN_CONFIRM
5.2.7.3. Constraint Extensions
Agents may implement experimental or private-use constraints through an extension constraint that supports named constraints ๐งช
byte SSH_AGENT_CONSTRAIN_EXTENSION
string extension name
byte[] extension-specific details
The "extension name" MUST consist of a UTF-8 string. Vendor extensions MUST be suffixed by the implementation domain, following the naming scheme defined in Section 6 of [RFC4251], e.g., "foo@example.com" ๐ท๏ธ
Note, given the above requirement to reject keys with unsupported constraints, a constraint extension is only usable when both the client and the agent support it. Otherwise, the agent will be required to reject the key. This is desirable, because the constraint extension may specify limits on the key. If those get ignored, the key could end up available in situations the user didn't intend. So the agent fails safely ๐ก๏ธ
5.3. Public Key Encoding
Keys that were previously loaded into an agent are referred to by their public key blob, which is the standard SSH wire encoding for public keys ๐ฆ SSH protocol key encodings are defined in [RFC4253] for "ssh-rsa" and "ssh-dss" keys, in [RFC5656] for "ecdsa-sha2-*" keys, and in [RFC8709] for "ssh-ed25519" and "ssh-ed448" keys ๐ฆ
5.4. Removing Keys from the Agent
A client may ask an agent to remove all the keys it stores ๐งน
byte SSH_AGENTC_REMOVE_ALL_IDENTITIES
When an agent gets this message, it SHOULD delete all the keys it is holding and reply with SSH_AGENT_SUCCESS. Otherwise, it MUST reply with SSH_AGENT_FAILURE if the request was refused ๐ซ
This request SHOULD be honoured regardless of any agent policy that limits what actions a given client may take. Otherwise, a user would be unable to quickly and completely remove their keys in an urgent situation ๐จ
Specific keys can also be removed ๐
byte SSH_AGENTC_REMOVE_IDENTITY
string key blob
Where key blob is the standard public key encoding of the key to be removed (Section 5.3).
An agent MUST reply with SSH_AGENT_SUCCESS if the key was deleted, or SSH_AGENT_FAILURE if it wasn't found ๐ โโ๏ธ
Token-hosted keys can be removed from an agent using:
byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
string token id
string PIN
Where token id is an opaque identifier for the hardware token, and PIN is an optional password or PIN (not typically used). Both are encoded using UTF-8 ๐ Requesting deletion of token-hosted keys SHOULD cause the agent to remove all keys it loaded from the device matching token id. Just like SSH_AGENTC_REMOVE_ALL_IDENTITIES, agents SHOULD honour this request regardless of local policy, so keys can be removed fast and completely ๐โโ๏ธ Removing a token-hosted key only affects the agent. It SHOULD NOT cause the keys to be deleted from the token itself ๐ง
An agent MUST reply with SSH_AGENT_SUCCESS if the keys were deleted, or SSH_AGENT_FAILURE if none were found ๐ธ
5.5. Requesting a List of Keys
A client may request a list of keys from an agent using the following message ๐
byte SSH_AGENTC_REQUEST_IDENTITIES
The agent MUST reply with a message that starts with the following preamble:
byte SSH_AGENT_IDENTITIES_ANSWER
uint32 nkeys
Where nkeys indicates how many keys follow. After the preamble come zero or more keys, representing the keys the agent makes available to the client. Each one is encoded as:
string key blob
string comment
Where key blob is the standard public key encoding of the key (Section 5.3), and comment is a human-readable comment encoded as a UTF-8 string ๐ฌ
5.6. Private Key Operations
A client may ask the agent to perform a private key signature operation using the following message ๐
byte SSH_AGENTC_SIGN_REQUEST
string key blob
string data
uint32 flags
Where key blob is the key requested to perform the signature (encoded as per Section 5.3), data is the data to be signed, and flags is a bitfield containing the bitwise OR of zero or more signature flags (see below) โจ
If the agent doesn't support the requested flags, or is otherwise unable or unwilling to generate the signature (for example, because it doesn't have the specified key, or because the user refused confirmation of a constrained key), it MUST reply with an SSH_AGENT_FAILURE message ๐ โโ๏ธ
On success, the agent MUST reply with:
byte SSH_AGENT_SIGN_RESPONSE
string signature
The signature format depends on the algorithm of the key type in use. SSH protocol signature formats are defined in [RFC4253] for "ssh-rsa" and "ssh-dss" keys, in [RFC5656] for "ecdsa-sha2-*" keys, and in [RFC8709] for "ssh-ed25519" and "ssh-ed448" keys ๐
5.6.1. Signature Flags
Two flags are currently defined for signature request messages: SSH_AGENT_RSA_SHA2_256 and SSH_AGENT_RSA_SHA2_512 (defined in Section 8.3). These two flags are only valid for "ssh-rsa" keys. They ask the agent to return a signature using the "rsa-sha2-256" or "rsa-sha2-512" signature methods, respectively. These signature schemes are defined in [RFC8332] ๐
5.7. Locking and Unlocking an Agent
The agent protocol lets you tell an agent to temporarily lock itself with a passphrase ๐ When locked, an agent MUST suspend processing of sensitive operations (private key signature operations at the very least) until it has been unlocked with the same passphrase. Sensitive stuff stays frozen until the right passphrase shows up ๐ฅถ
The following message tells an agent to lock itself:
byte SSH_AGENTC_LOCK
string passphrase
The agent MUST reply with SSH_AGENT_SUCCESS if it locked successfully, or SSH_AGENT_FAILURE otherwise (e.g., if the agent was already locked) ๐ซง
The following message requests unlocking an agent:
byte SSH_AGENTC_UNLOCK
string passphrase
If the agent is already locked and the passphrase matches the one used to lock it, then it MUST unlock and reply with SSH_AGENT_SUCCESS. If the agent is already unlocked, or if the passphrase doesn't match, it MUST reply with SSH_AGENT_FAILURE ๐๐
5.8. Extension Mechanism ๐ง
Okay so the agent protocol has this optional extension mechanism that lets vendor-specific and experimental messages get sent through the agent protocol ๐ Extension requests from the client look like this:
byte SSH_AGENTC_EXTENSION
string extension type
byte[] extension request-specific contents
The "extension type" tells you what kind of extension message it is, and it's a UTF-8 string. Implementation-specific extensions MUST be suffixed by the implementation domain, following the extension naming scheme from Section 6 of [RFC4251], e.g., "foo@example.com" ๐
An agent that doesn't support extensions of the supplied type MUST reply with an empty SSH_AGENT_FAILURE message. Agents that don't support the extension mechanism at all also send this reply. ๐
The contents of successful extension replies depend on the "extension type." Successful extension requests MUST return either SSH_AGENT_SUCCESS on success or an extension-specific response message:
byte SSH_AGENT_EXTENSION_RESPONSE
string extension type
byte[] extension response-specific contents
Where the "extension type" is the same as the one in the request โจ
Extension failure SHOULD be signaled using an SSH_AGENT_EXTENSION_FAILURE message:
byte SSH_AGENT_EXTENSION_FAILURE
Extensions SHOULD NOT use the standard SSH_AGENT_FAILURE message. This way, failed requests can be told apart from the extension just not being supported. Iconic behaviour, honestly ๐
5.8.1. Query Extension
One optional extension request, "query," is defined so a client can ask which extensions (if any) an agent supports ๐
byte SSH_AGENTC_EXTENSION
string "query"
If an agent supports the query extension, it SHOULD reply with a list of supported extension names.
byte SSH_AGENT_EXTENSION_RESPONSE
string "query"
string[] supported extension types
6. Connecting to an Agent ๐ฆ
Agents are exposed to the local system using a connection-oriented endpoint. On Unix-like systems, it's typical to have the agent listen on a filesystem-based Unix domain socket. On Microsoft Windows, a Windows Named Pipe is the usual choice. Access to these endpoints SHOULD be controlled as discussed in Section 10. Multiple clients can access a single agent by connecting to these sockets ๐ธ
In both cases, it's common to expose the name or address of the listening endpoint through an environment variable named "SSH_AUTH_SOCK". Clients use this variable to find and connect to the listening agent. Alternatively, agents MAY use an implicit mechanism for clients to locate their endpoint, such as a default per-user location ๐ง
7. Forwarding Access to an Agent ๐
Using the connection protocol described in [RFC4254], the agent protocol may be forwarded over an SSH connection. This lets agent forwarding be requested for any session channel, using a model similar to the connection protocol's support for X11 Forwarding (Section 6.3 of [RFC4254]). This feature is OPTIONAL for the SSH protocol and agent implementations โญ
7.1. Advertising Agent Forwarding Support
Support for agent forwarding may be advertised by an SSH server using the extension mechanism described in [RFC8308], using the name "agent-forward" in the SSH_MSG_EXT_INFO message ๐ฃ
string "agent-forward"
string "0" (version)
Note that this protocol substantially predates the existence of the extension mechanism described in [RFC8308]. Further note that several widely deployed SSH implementations that support agent forwarding don't advertise their ability to do so, which is so relatable ๐ญ SSH clients MAY opportunistically attempt to request agent forwarding in the absence of an advertisement (see [RFC8308]) using the vendor-specific names mentioned below. Likewise, SSH servers MAY implement the vendor-specific names in addition to the one described here ๐ซถ
7.2. Requesting Agent Forwarding
An SSH client may request agent forwarding for a previously opened session (see Section 6.1 of [RFC4254]) using the following channel request. The client sends this request after the channel has been opened, but before a shell, command, or subsystem has been executed ๐
byte SSH_MSG_CHANNEL_REQUEST
uint32 channel_id
string "agent-req" or "auth-agent-req@openssh.com"
boolean want_reply
Where "channel_id" is the identifier for an established session channel (as returned from a previous SSH_MSG_CHANNEL_OPEN request), and the "want_reply" flag indicates whether the SSH server should respond with a confirmation of whether the request was successful (as specified in Section 5.4 of [RFC4254]) ๐
If an SSH server accepts this request, it will typically arrange to make an endpoint (e.g., a listening socket) available and advertise this fact to the subordinate session. Most implementations on Unix-like systems do this by providing a user-private listening Unix domain socket and recording its location in an environment variable "SSH_AUTH_SOCK" ๐
As mentioned previously, many deployed implementations only support the pre-standardisation "auth-agent-req@openssh.com" request name. The "agent-req" name SHOULD only be used if support was explicitly advertised as per Section 7.1 ๐
7.3. Agent Connection Requests
After an SSH client has requested that a session have agent forwarding enabled, the SSH server may request a connection to the forwarded agent. It does this by requesting a dedicated channel to communicate with the SSH client's agent ๐ก
byte SSH_MSG_CHANNEL_OPEN
string "agent-connect" or "auth-agent@openssh.com"
uint32 channel_id
uint32 local_window
uint32 local_maxpacket
The "channel_id", "local_window", and "local_maxpacket" fields should be interpreted as specified by Section 5.1 of [RFC4254] ๐ง
As above, the "agent-connect" open type name SHOULD only be used if support was explicitly advertised as per Section 7.1 ๐
An SSH client SHOULD be prepared to handle multiple concurrent forwarded connections to a client-side agent. Otherwise, requests to access the agent from the remote side that happen to overlap prior requests may fail. Overlapping requests can happen because the SSH connection protocol [RFC4254] allows multiple user sessions over a single transport (see [RFC4253]), and each one may request use of the agent independently and potentially concurrently. Multitasking, but make it networking ๐
An SSH client MAY accept agent connection requests (subject to authorisation) without a prior agent forwarding request having been made, to support the situation where agent forwarding without opening a session is desired. Similarly, an SSH client MAY continue to accept agent connection requests after the session for which agent forwarding was requested has closed ๐
An SSH client MUST refuse unauthorised agent connection requests when agent forwarding is neither requested nor desired by the SSH client, but an SSH server sends an agent connection request anyway. Not the server just barging in ๐ซ
Because the "agent-connect" request contains no identifier to distinguish which session channel originated the connection request, an SSH connection can effectively forward access to only a single SSH client-side agent using this protocol (although there may be multiple concurrent connections to that single agent). ๐ฅบ
8. Protocol Numbers ๐ข
8.1. Message Type Numbers
The following numbers are used as message types for requests from the client to the agent ๐
+------------------------------------------+----+
| SSH_AGENTC_REQUEST_IDENTITIES | 11 |
+------------------------------------------+----+
| SSH_AGENTC_SIGN_REQUEST | 13 |
+------------------------------------------+----+
| SSH_AGENTC_ADD_IDENTITY | 17 |
+------------------------------------------+----+
| SSH_AGENTC_REMOVE_IDENTITY | 18 |
+------------------------------------------+----+
| SSH_AGENTC_REMOVE_ALL_IDENTITIES | 19 |
+------------------------------------------+----+
| SSH_AGENTC_ADD_SMARTCARD_KEY | 20 |
+------------------------------------------+----+
| SSH_AGENTC_REMOVE_SMARTCARD_KEY | 21 |
+------------------------------------------+----+
| SSH_AGENTC_LOCK | 22 |
+------------------------------------------+----+
| SSH_AGENTC_UNLOCK | 23 |
+------------------------------------------+----+
| SSH_AGENTC_ADD_ID_CONSTRAINED | 25 |
+------------------------------------------+----+
| SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED | 26 |
+------------------------------------------+----+
| SSH_AGENTC_EXTENSION | 27 |
+------------------------------------------+----+
Table 1
The following numbers are used as message types for replies from the agent to the client ๐ฆ
+------------------------------+----+
| SSH_AGENT_FAILURE | 5 |
+------------------------------+----+
| SSH_AGENT_SUCCESS | 6 |
+------------------------------+----+
| SSH_AGENT_IDENTITIES_ANSWER | 12 |
+------------------------------+----+
| SSH_AGENT_SIGN_RESPONSE | 14 |
+------------------------------+----+
| SSH_AGENT_EXTENSION_FAILURE | 28 |
+------------------------------+----+
| SSH_AGENT_EXTENSION_RESPONSE | 29 |
+------------------------------+----+
Table 2
8.1.1. Reserved Message Type Numbers
The following message type numbers are reserved for implementations that support the legacy SSH protocol version 1: 1-4, 7-10, 15-16, and 24 (inclusive). These message numbers MAY be used by an implementation supporting the legacy protocol, but MUST NOT be reused otherwise ๐ฐ๏ธ
Message number 0 is also reserved and MUST NOT be used. Zero is off-limits, bestie ๐ โโ๏ธ
The range of message numbers 240-255 is reserved for Private Use extensions to the agent protocol and MUST NOT be used by generic implementations (see [RFC8126] for more information on Private Use) ๐
8.2. Constraint Identifiers
The following numbers are used to identify key constraints. These are only used in key constraints and are not sent as message numbers ๐ฏ
+-------------------------------+-----+
| SSH_AGENT_CONSTRAIN_LIFETIME | 1 |
+-------------------------------+-----+
| SSH_AGENT_CONSTRAIN_CONFIRM | 2 |
+-------------------------------+-----+
| SSH_AGENT_CONSTRAIN_EXTENSION | 255 |
+-------------------------------+-----+
Table 3
The constraint identifier 0 is reserved ๐ธ
8.3. Signature Flags ๐ โจ
okay so this part is all about the flags you can slap onto a signature request (SSH_AGENTC_SIGN_REQUEST) message ๐ these numbers get combined with a bitwise OR, so you can stack zero or more of them together ๐ซถ
Here's the lineup ๐ธ
+------------------------+------------+
| SSH_AGENT_RSA_SHA2_256 | 0x00000002 |
+------------------------+------------+
| SSH_AGENT_RSA_SHA2_512 | 0x00000004 |
+------------------------+------------+
Table 4
ngl the flag value 1 is reserved for historical implementations ๐ it's giving "we've been here before" energy, so don't go grabbing it for something new ๐
9. IANA Considerations ๐ฆ
okay so this protocol sets up five registries ๐ one for message type numbers, one for constraint numbers, one for signature request flags, one for constraint extension names, and one for extension request names. on top of that, new codepoints are requested in three existing registries โจ
9.1. Guidance for Designated Experts ๐
when a Designated Expert (DE) gets asked to review additions to the new registries from this document (Section 9.2, Section 9.3, Section 9.5, and Section 9.6), they're asked to check that suitable documentation, like the kind described in [RFC8126], exists and is permanently and publicly available ๐ the DE is also asked to check how clear the purpose and use of the requested codepoints are ๐ the DE should also verify that IETF specs requesting codepoints in these registries have been made available to the SSHM Working Group and the ssh@ietf.org mailing list for review ๐ and if a request comes from a spec produced outside the IETF, it should not conflict with active IETF work or prior IETF specifications ๐ซถ
the SSH agent protocol numbers (Section 9.2), constraint numbers (Section 9.3), and SSH agent signature flags (Section 9.5) registries have a limited number of codepoints available, so the DE is asked to make sure every codepoint is very well justified ๐ฅบ for SSH agent protocol message numbers, named extension requests (Section 9.6) are the alternative for most uses, and there's no practical limit on how many of those you can get ๐ง for key constraint numbers, the constraint extension mechanism (Section 5.2.7.3) gives you a similar alternative that isn't limited by available codepoints ๐ main character energy for the extension route, honestly ๐ญ
9.2. "SSH Agent Protocol Message Type Numbers" Registry โจ
okay so this registry is where all the message type numbers for client requests and agent responses live ๐๏ธ it's tucked inside the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH], which is giving very organized energy ๐ it starts out with the numbers and reservations listed below. any new message number gets handed out through Expert Review as per [RFC8126] ๐ซถ
+=========+==========================================+=============+
| Number | Identifier | Reference |
+=========+==========================================+=============+
| 0 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 1 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 2 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 3 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 4 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 5 | SSH_AGENT_FAILURE | RFC 9987, |
| | | Sections |
| | | 5.1 and 8.1 |
+---------+------------------------------------------+-------------+
| 6 | SSH_AGENT_SUCCESS | RFC 9987, |
| | | Sections |
| | | 5.1 and 8.1 |
+---------+------------------------------------------+-------------+
| 7 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 8 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 9 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 10 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 11 | SSH_AGENTC_REQUEST_IDENTITIES | RFC 9987, |
| | | Sections |
| | | 5.5 and 8.1 |
+---------+------------------------------------------+-------------+
| 12 | SSH_AGENT_IDENTITIES_ANSWER | RFC 9987, |
| | | Sections |
| | | 5.5 and 8.1 |
+---------+------------------------------------------+-------------+
| 13 | SSH_AGENTC_SIGN_REQUEST | RFC 9987, |
| | | Sections |
| | | 5.6 and 8.1 |
+---------+------------------------------------------+-------------+
| 14 | SSH_AGENT_SIGN_RESPONSE | RFC 9987, |
| | | Sections |
| | | 5.6 and 8.1 |
+---------+------------------------------------------+-------------+
| 15 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 16 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 17 | SSH_AGENTC_ADD_IDENTITY | RFC 9987, |
| | | Sections |
| | | 5.2 and 8.1 |
+---------+------------------------------------------+-------------+
| 18 | SSH_AGENTC_REMOVE_IDENTITY | RFC 9987, |
| | | Sections |
| | | 5.4 and 8.1 |
+---------+------------------------------------------+-------------+
| 19 | SSH_AGENTC_REMOVE_ALL_IDENTITIES | RFC 9987, |
| | | Sections |
| | | 5.4 and 8.1 |
+---------+------------------------------------------+-------------+
| 20 | SSH_AGENTC_ADD_SMARTCARD_KEY | RFC 9987, |
| | | Sections |
| | | 5.2.6 and |
| | | 8.1 |
+---------+------------------------------------------+-------------+
| 21 | SSH_AGENTC_REMOVE_SMARTCARD_KEY | RFC 9987, |
| | | Sections |
| | | 5.4 and 8.1 |
+---------+------------------------------------------+-------------+
| 22 | SSH_AGENTC_LOCK | RFC 9987, |
| | | Sections |
| | | 5.7 and 8.1 |
+---------+------------------------------------------+-------------+
| 23 | SSH_AGENTC_UNLOCK | RFC 9987, |
| | | Sections |
| | | 5.7 and 8.1 |
+---------+------------------------------------------+-------------+
| 24 | Reserved | RFC 9987, |
| | | Section |
| | | 8.1.1 |
+---------+------------------------------------------+-------------+
| 25 | SSH_AGENTC_ADD_ID_CONSTRAINED | RFC 9987, |
| | | Sections |
| | | 5.2 and 8.1 |
+---------+------------------------------------------+-------------+
| 26 | SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED | RFC 9987, |
| | | Sections |
| | | 5.2.6 and |
| | | 8.1 |
+---------+------------------------------------------+-------------+
| 27 | SSH_AGENTC_EXTENSION | RFC 9987, |
| | | Sections |
| | | 5.8 and 8.1 |
+---------+------------------------------------------+-------------+
| 28 | SSH_AGENT_EXTENSION_FAILURE | RFC 9987, |
| | | Sections |
| | | 5.8 and 8.1 |
+---------+------------------------------------------+-------------+
| 29 | SSH_AGENT_EXTENSION_RESPONSE | RFC 9987, |
| | | Sections |
| | | 5.8 and 8.1 |
+---------+------------------------------------------+-------------+
| 240-255 | Private Use | RFC 9987, |
| | | Section 8.1 |
+---------+------------------------------------------+-------------+
Table 5
9.3. "SSH Agent Key Constraint Numbers" Registry ๐
this one records the message numbers for key use constraints ๐ same deal, it lives in the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH], and new key constraint numbers also come through Expert Review as per [RFC8126] ๐ here's how it starts out:
+========+===============================+=======================+
| Number | Identifier | Reference |
+========+===============================+=======================+
| 0 | Reserved | RFC 9987, Section 8.2 |
+--------+-------------------------------+-----------------------+
| 1 | SSH_AGENT_CONSTRAIN_LIFETIME | RFC 9987, Section 8.2 |
+--------+-------------------------------+-----------------------+
| 2 | SSH_AGENT_CONSTRAIN_CONFIRM | RFC 9987, Section 8.2 |
+--------+-------------------------------+-----------------------+
| 255 | SSH_AGENT_CONSTRAIN_EXTENSION | RFC 9987, Section 8.2 |
+--------+-------------------------------+-----------------------+
Table 6
9.4. "SSH Agent Key Constraint Extension Names" Registry ๐ง
last but definitely not least ๐ธ this registry records the names used in the SSH_AGENT_CONSTRAIN_EXTENSION constraint extension type (Section 5.2.7.3). it's also in the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH]. the big news is that it starts out totally empty ๐ซง any future key constraint extension names get allocated through Expert Review as per [RFC8126], so the list grows from here ๐
9.5. "SSH Agent Signature Flags" Registry โจ
okay so the "SSH Agent Signature Flags" registry is where we keep track of the values for signature request (SSH_AGENTC_SIGN_REQUEST) flags ๐ It lives in the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH], and here's the starting lineup of numbers. ngl the big thing to know is that flags get combined with bitwise OR, so every flag value must be a power of two, and the highest one you can have is 0x80000000. that's the whole math trick ๐งฎ
Future signature flags get handed out via Expert Review as per [RFC8126] ๐ซถ
+========+========================+=======================+
| Number | Identifier | Reference |
+========+========================+=======================+
| 0x01 | Reserved | RFC 9987, Section 8.3 |
+--------+------------------------+-----------------------+
| 0x02 | SSH_AGENT_RSA_SHA2_256 | RFC 9987, Section 8.3 |
+--------+------------------------+-----------------------+
| 0x04 | SSH_AGENT_RSA_SHA2_512 | RFC 9987, Section 8.3 |
+--------+------------------------+-----------------------+
Table 7
9.6. "SSH Agent Extension Request Names" Registry ๐ธ
the "SSH Agent Extension Request Names" registry tracks the names used in the generic extension request message (SSH_AGENTC_EXTENSION) ๐ง It's also in the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH], and it starts off with just one name.
Future name allocations shall occur via Expert Review as per [RFC8126] ๐
+================+=========================+
| Extension Name | Reference |
+================+=========================+
| query | RFC 9987, Section 5.8.1 |
+----------------+-------------------------+
Table 8
9.7. Additions to the "Extension Names" Registry ๐ฆ
IANA has added the following entries to the "Extension Names" registry [IANA-SSH-EXT] in the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH]. main character entry: agent-forward ๐
+================+=======================+
| Extension Name | Reference |
+================+=======================+
| agent-forward | RFC 9987, Section 7.1 |
+----------------+-----------------------+
Table 9
9.8. Additions to the "Connection Protocol Channel Request Names" Registry ๐
IANA has added the following entries to the "Connection Protocol Channel Request Names" registry [IANA-SSH-CHANREQ] in the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH]. the new request type is agent-req โจ
+==============+=======================+
| Request Type | Reference |
+==============+=======================+
| agent-req | RFC 9987, Section 7.2 |
+--------------+-----------------------+
Table 10
9.9. Additions to the "Connection Protocol Channel Types" Registry ๐
IANA has added the following entries to the "Connection Protocol Channel Types" registry [IANA-SSH-CHANTYPE] under the "Secure Shell (SSH) Protocol Parameters" registry group [IANA-SSH]. and the new channel type is agent-connect ๐
+===============+=======================+
| Channel Type | Reference |
+===============+=======================+
| agent-connect | RFC 9987, Section 7.3 |
+---------------+-----------------------+
Table 11
10. Security Considerations ๐ฅ
okay bestie, this section is the serious one ๐ญ The agent is basically the guardian of long-lived login authentication credentials. By nature it's a sensitive and trusted software component. And the agent protocol itself has no authentication or transport security at all, so being able to talk to an agent is usually enough to get it to perform private key operations. yikes ๐
Since being able to reach an agent is usually enough to run private key operations, it is critically important that the agent only be exposed to its owner and their authorised delegates ๐ On Unix-like systems, that can be handled with filesystem permissions on the agent socket and/or identity checks on the client connected to a socket (e.g., SO_PEERCRED on some Unix-like systems). On Windows, you can control access to a named pipe by attaching a security descriptor when it's created.
The main design goal of an agent is that an attacker with unprivileged access to their victim's agent should be stopped from getting a copy of any keys loaded into it. That may not stop the attacker from stealing use of those keys, though (e.g., if they have been loaded without a confirmation constraint). not ideal, not ideal ๐
So, as far as possible, the agent should stop its memory from being read by other processes, so loaded keys can't be stolen. Typically this means disabling debugging interfaces and preventing process memory dumps on abnormal termination ๐ก๏ธ
Another, sneakier way keys can get stolen is through cryptographic side-channels. Private key operations can leak information about key contents through differences in timing, power use, or side effects in the memory subsystems (e.g., CPU caches) of the host running the agent ๐ For a local attacker and an agent holding unconstrained keys, the only limit on how many private key operations the attacker can observe is how fast the CPU can perform signatures. that's basically an almost ideal oracle for side-channel attacks, and it's giving danger ๐ฑ A full treatment of side-channel attacks is beyond the scope of this specification, but agents SHOULD use cryptographic implementations that are resistant to side-channel attacks and MAY take additional measures to hide the actual time spent processing private key operations. skipping this may expose keys to recovery through these side-channels.
Forwarding access to a local agent over an SSH connection (Section 7) inherently creates a transitive trust relationship ๐ฆ SSH implementations SHOULD NOT forward use of an agent by default, and users SHOULD NOT forward use of an agent to hosts that aren't fully trusted, because that could expose access to the user's keys to attackers on remote hosts. Agents SHOULD implement additional controls over key visibility and use for forwarded agent connections. otherwise, the user only gets an all-or-nothing choice about whether to forward an agent ๐ โโ๏ธ
Tokens and smartcards hosting keys need some care too ๐ On some systems, a token may be invoked by providing a path to a shared library that must be loaded to use the keys on the device (a path to a library for a particular PKCS#11 module, for example). Loading a shared library on most platforms means the code in that library automatically runs in the address space of the process that loads it. To avoid loading potentially hostile code, agents that support loading token-hosted keys via a library path SHOULD ensure that only trusted token provider libraries are loadable. Agents SHOULD also ensure that loaded token library code cannot gain access to other keys loaded in the agent, and MAY disallow remote clients from loading token keys entirely. protection for existing keys from token library code can be done by loading the token library into a separate process from the agent and having the agent invoke token operations in that process via IPC ๐ง
Finally, with respect to the agent locking functionality in Section 5.7, an agent SHOULD take countermeasures against brute-force guessing attacks on the passphrase ๐ This can look like enforced delays when an unlock attempt is made with an incorrect password (potentially increasing for subsequent failures), a lockout period where the agent refuses to accept further requests after a threshold of failed unlock attempts, and/or deleting all keys the agent holds after a threshold of failed unlock attempts. the goal is to make guessing a total waste of time ๐
11. References ๐
11.1. Normative References
- [FIPS.186-4] NIST, "Digital Signature Standard (DSS)", NIST FIPS 186-4, DOI 10.6028/NIST.FIPS.186-4, June 2013,
https://doi.org/10.6028/NIST.FIPS.186-4. - [FIPS.186-5] NIST, "Digital Signature Standard (DSS)", NIST FIPS 186-5, DOI 10.6028/NIST.FIPS.186-5, February 2023,
https://doi.org/10.6028/NIST.FIPS.186-5. - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,
https://www.rfc-editor.org/info/rfc2119. - [RFC4251] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Protocol Architecture", RFC 4251, DOI 10.17487/RFC4251, January 2006,
https://www.rfc-editor.org/info/rfc4251. - [RFC4253] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Transport Layer Protocol", RFC 4253, DOI 10.17487/RFC4253, January 2006,
https://www.rfc-editor.org/info/rfc4253. - [RFC4254] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Connection Protocol", RFC 4254, DOI 10.17487/RFC4254, January 2006,
https://www.rfc-editor.org/info/rfc4254. - [RFC5656] Stebila, D. and J. Green, "Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer", RFC 5656, DOI 10.17487/RFC5656, December 2009,
https://www.rfc-editor.org/info/rfc5656. - [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, January 2017,
https://www.rfc-editor.org/info/rfc8032. - [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017,
https://www.rfc-editor.org/info/rfc8174. - [RFC8308] Bider, D., "Extension Negotiation in the Secure Shell (SSH) Protocol", RFC 8308, DOI 10.17487/RFC8308, March 2018,
https://www.rfc-editor.org/info/rfc8308. - [RFC8332] Bider, D., "Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol", RFC 8332, DOI 10.17487/RFC8332, March 2018,
https://www.rfc-editor.org/info/rfc8332. - [RFC8709] Harris, B. and L. Velvindron, "Ed25519 and Ed448 Public Key Algorithms for the Secure Shell (SSH) Protocol", RFC 8709, DOI 10.17487/RFC8709, February 2020,
https://www.rfc-editor.org/info/rfc8709.
11.2. Informative References ๐
Okay bestie, this is the "good to know, not required" reading list ๐คโจ. The IANA entries are basically the group chat's shared spreadsheets ๐ , and they all live at the same SSH parameters page.
- [IANA-PUBKEYS] IANA, "Public Key Algorithm Names",
<https://www.iana.org/assignments/ssh-parameters/>. - [IANA-SSH] IANA, "Secure Shell (SSH) Protocol Parameters",
<https://www.iana.org/assignments/ssh-parameters/>. - [IANA-SSH-CHANREQ] IANA, "Connection Protocol Channel Types",
<https://www.iana.org/assignments/ssh-parameters/>. - [IANA-SSH-CHANTYPE] IANA, "Extension Names",
<https://www.iana.org/assignments/ssh-parameters/>. - [IANA-SSH-EXT] IANA, "Connection Protocol Channel Request Names",
<https://www.iana.org/assignments/ssh-parameters/>. - [RFC4252] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) Authentication Protocol", RFC 4252, DOI 10.17487/RFC4252, January 2006,
<https://www.rfc-editor.org/info/rfc4252>. - [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>.
Acknowledgments ๐ซถ
This protocol was designed and first implemented by Markus Friedl, based on a similar protocol for an agent to support the legacy SSH version 1 by Tatu Ylonen. Main character origin story, honestly ๐.
Thanks to Simon Tatham, Niels Mรถller, James Spencer, Simon Josefsson, Matt Johnston, Jakub Jelen, Rich Salz, Caspar Schutijser, Florian Obser, Martin Thomson, Deb Cooley, and Tero Kivinen, who reviewed and helped improve this document. Literally the whole squad showed up for this one ๐๐ธ.
Author's Address ๐
Damien Miller
OpenSSH
Email: djm@openssh.com
URI: https://www.openssh.com/
๐ฆ where this page comes from
- ietf: rfc9987 2026-05
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms