Skip to content

Module ssh_agent_client

ssh_agent_client

A bare-bones SSH agent client supporting signing and key listing.

TrailingDataError

TrailingDataError()

Bases: RuntimeError

The result contained trailing data.

SSHAgentClient

SSHAgentClient(
    *,
    socket: socket.socket | None = None,
    timeout: int = 125
)

A bare-bones SSH agent client supporting signing and key listing.

The main use case is requesting the agent sign some data, after checking that the necessary key is already loaded.

The main fleshed out methods are list_keys and sign, which implement the REQUEST_IDENTITIES and SIGN_REQUEST requests. If you really wanted to, there is enough infrastructure in place to issue other requests as defined in the protocol—it’s merely the wrapper functions and the protocol numbers table that are missing.

Parameters:

Name Type Description Default
socket socket | None

An optional socket, connected to the SSH agent. If not given, we query the SSH_AUTH_SOCK environment variable to auto-discover the correct socket address.

None
timeout int

A connection timeout for the SSH agent. Only used if the socket is not yet connected. The default value gives ample time for agent connections forwarded via SSH on high-latency networks (e.g. Tor).

125

Raises:

Type Description
KeyError

The SSH_AUTH_SOCK environment was not found.

OSError

There was an error setting up a socket connection to the agent.

__enter__

__enter__() -> Self

Close socket connection upon context manager completion.

__exit__

__exit__(
    exc_type: type[BaseException] | None,
    exc_val: BaseException | None,
    exc_tb: TracebackType | None,
) -> bool

Close socket connection upon context manager completion.

uint32 staticmethod

uint32(num: int) -> bytes

Format the number as a uint32, as per the agent protocol.

Parameters:

Name Type Description Default
num int

A number.

required

Returns:

Type Description
bytes

The number in SSH agent wire protocol format, i.e. as a 32-bit big endian number.

Raises:

Type Description
OverflowError

As per int.to_bytes.

Examples:

>>> SSHAgentClient.uint32(16777216)
b'\x01\x00\x00\x00'

string classmethod

string(payload: bytes | bytearray) -> bytes | bytearray

Format the payload as an SSH string, as per the agent protocol.

Parameters:

Name Type Description Default
payload bytes | bytearray

A byte string.

required

Returns:

Type Description
bytes | bytearray

The payload, framed in the SSH agent wire protocol format.

Examples:

>>> bytes(SSHAgentClient.string(b'ssh-rsa'))
b'\x00\x00\x00\x07ssh-rsa'

unstring classmethod

unstring(
    bytestring: bytes | bytearray,
) -> bytes | bytearray

Unpack an SSH string.

Parameters:

Name Type Description Default
bytestring bytes | bytearray

A framed byte string.

required

Returns:

Type Description
bytes | bytearray

The unframed byte string, i.e., the payload.

Raises:

Type Description
ValueError

The byte string is not an SSH string.

Examples:

>>> bytes(SSHAgentClient.unstring(b'\x00\x00\x00\x07ssh-rsa'))
b'ssh-rsa'
>>> bytes(
...     SSHAgentClient.unstring(SSHAgentClient.string(b'ssh-ed25519'))
... )
b'ssh-ed25519'

unstring_prefix classmethod

unstring_prefix(
    bytestring: bytes | bytearray,
) -> tuple[bytes | bytearray, bytes | bytearray]

Unpack an SSH string at the beginning of the byte string.

Parameters:

Name Type Description Default
bytestring bytes | bytearray

A (general) byte string, beginning with a framed/SSH byte string.

required

Returns:

Type Description
tuple[bytes | bytearray, bytes | bytearray]

A 2-tuple (a, b), where a is the unframed byte string/payload at the beginning of input byte string, and b is the remainder of the input byte string.

Raises:

Type Description
ValueError

The byte string does not begin with an SSH string.

Examples:

>>> a, b = SSHAgentClient.unstring_prefix(
...     b'\x00\x00\x00\x07ssh-rsa____trailing data'
... )
>>> (bytes(a), bytes(b))
(b'ssh-rsa', b'____trailing data')
>>> a, b = SSHAgentClient.unstring_prefix(
...     SSHAgentClient.string(b'ssh-ed25519')
... )
>>> (bytes(a), bytes(b))
(b'ssh-ed25519', b'')

request

request(
    code: int, payload: bytes | bytearray
) -> tuple[int, bytes | bytearray]

Issue a generic request to the SSH agent.

Parameters:

Name Type Description Default
code int

The request code. See the SSH agent protocol for protocol numbers to use here (and which protocol numbers to expect in a response).

required
payload bytes | bytearray

A byte string containing the payload, or “contents”, of the request. Request-specific. request will add any necessary wire framing around the request code and the payload.

required

Returns:

Type Description
tuple[int, bytes | bytearray]

A 2-tuple consisting of the response code and the payload, with all wire framing removed.

Raises:

Type Description
EOFError

The response from the SSH agent is truncated or missing.

list_keys

list_keys() -> Sequence[types.KeyCommentPair]

Request a list of keys known to the SSH agent.

Returns:

Type Description
Sequence[KeyCommentPair]

A read-only sequence of key/comment pairs.

Raises:

Type Description
EOFError

The response from the SSH agent is truncated or missing.

TrailingDataError

The response from the SSH agent is too long.

RuntimeError

The agent failed to complete the request.

sign

sign(
    key: bytes | bytearray,
    payload: bytes | bytearray,
    *,
    flags: int = 0,
    check_if_key_loaded: bool = False
) -> bytes | bytearray

Request the SSH agent sign the payload with the key.

Parameters:

Name Type Description Default
key bytes | bytearray

The public SSH key to sign the payload with, in the same format as returned by, e.g., the list_keys method. The corresponding private key must have previously been loaded into the agent to successfully issue a signature.

required
payload bytes | bytearray

A byte string of data to sign.

required
flags int

Optional flags for the signing request. Currently passed on as-is to the agent. In real-world usage, this could be used, e.g., to request more modern hash algorithms when signing with RSA keys. (No such real-world usage is currently implemented.)

0
check_if_key_loaded bool

If true, check beforehand (via list_keys) if the corresponding key has been loaded into the agent.

False

Returns:

Type Description
bytes | bytearray

The binary signature of the payload under the given key.

Raises:

Type Description
EOFError

The response from the SSH agent is truncated or missing.

TrailingDataError

The response from the SSH agent is too long.

RuntimeError

The agent failed to complete the request.

KeyError

check_if_key_loaded is true, and the key was not loaded into the agent.

types

Common typing declarations for the parent module.

KeyCommentPair

Bases: NamedTuple

SSH key plus comment pair. For typing purposes.

Attributes:

Name Type Description
key bytes | bytearray

SSH key.

comment bytes | bytearray

SSH key comment.

SSH_AGENTC

Bases: Enum

SSH agent protocol numbers: client requests.

Attributes:

Name Type Description
REQUEST_IDENTITIES int

List identities. Expecting SSH_AGENT.IDENTITIES_ANSWER.

SIGN_REQUEST int

Sign data. Expecting SSH_AGENT.SIGN_RESPONSE.

SSH_AGENT

Bases: Enum

SSH agent protocol numbers: server replies.

Attributes:

Name Type Description
IDENTITIES_ANSWER int

Successful answer to SSH_AGENTC.REQUEST_IDENTITIES.

SIGN_RESPONSE int

Successful answer to SSH_AGENTC.SIGN_REQUEST.