Structures

This package provides many common structures generally used in Command, Reply or Event.

Enumerations

These classes are used to enumerate various items such as list of purposes, error reasons, available flags, authentication methods, etc…

class aiostem.structures.AuthMethod[source]

Bases: StrEnum

Known authentication methods on the control port..

NULL = 'NULL'

No authentication is required.

HASHEDPASSWORD = 'HASHEDPASSWORD'

A simple password authentication (hashed in the configuration file).

COOKIE = 'COOKIE'

Provide the content of a cookie we read on the file-system.

SAFECOOKIE = 'SAFECOOKIE'

Provide a proof that we know the value of the cookie on the file-system.

class aiostem.structures.CircuitBuildFlags[source]

Bases: StrEnum

Known flags when building a new circuit.

ONEHOP_TUNNEL = 'ONEHOP_TUNNEL'

One-hop circuit, used for tunneled directory conns.

IS_INTERNAL = 'IS_INTERNAL'

Internal circuit, not to be used for exiting streams.

NEED_CAPACITY = 'NEED_CAPACITY'

This circuit must use only high-capacity nodes.

NEED_UPTIME = 'NEED_UPTIME'

This circuit must use only high-uptime nodes.

class aiostem.structures.CircuitCloseReason[source]

Bases: StrEnum

Known reasons why a circuit can be closed.

NONE = 'NONE'

No reason given.

PROTOCOL = 'PROTOCOL'

Tor protocol violation.

INTERNAL = 'INTERNAL'

Internal error.

REQUESTED = 'REQUESTED'

A client sent a TRUNCATE command.

HIBERNATING = 'HIBERNATING'

Not currently operating; trying to save bandwidth.

RESOURCELIMIT = 'RESOURCELIMIT'

Out of memory, sockets, or circuit IDs.

CONNECTFAILED = 'CONNECTFAILED'

Unable to reach relay.

OR_IDENTITY = 'OR_IDENTITY'

Connected to relay, but its OR identity was not as expected.

CHANNEL_CLOSED = 'CHANNEL_CLOSED'

The OR connection that was carrying this circuit died.

FINISHED = 'FINISHED'

The circuit has expired for being dirty or old.

TIMEOUT = 'TIMEOUT'

Circuit construction took too long.

DESTROYED = 'DESTROYED'

The circuit was destroyed w/o client TRUNCATE.

NOSUCHSERVICE = 'NOSUCHSERVICE'

Request for unknown hidden service.

NOPATH = 'NOPATH'

Not enough nodes to make circuit.

MEASUREMENT_EXPIRED = 'MEASUREMENT_EXPIRED'

As “TIMEOUT”, except that we had left the circuit open for measurement purposes.

This is to see how long it would take to finish.

IP_NOW_REDUNDANT = 'IP_NOW_REDUNDANT'

Closing a circuit to an introduction point that has become redundant.

Since some other circuit opened in parallel with it has succeeded.

class aiostem.structures.CircuitEvent[source]

Bases: StrEnum

List of existing circuit events.

CANNIBALIZED = 'CANNIBALIZED'

Circuit cannibalized.

PURPOSE_CHANGED = 'PURPOSE_CHANGED'

Circuit purpose or HS-related state changed.

class aiostem.structures.CircuitHiddenServicePow[source]

Bases: object

Hidden service PoW effort attached to a circuit.

type: str

The type of proof of work system used (currently v1).

effort: Annotated[int]

Proof of work effort associated with this circuit.

class aiostem.structures.CircuitHiddenServiceState[source]

Bases: StrEnum

State of a hidden service circuit.

HSCI_CONNECTING = 'HSCI_CONNECTING'
HSCI_INTRO_SENT = 'HSCI_INTRO_SENT'
HSCI_DONE = 'HSCI_DONE'
HSCR_CONNECTING = 'HSCR_CONNECTING'
HSCR_ESTABLISHED_IDLE = 'HSCR_ESTABLISHED_IDLE'
HSCR_ESTABLISHED_WAITING = 'HSCR_ESTABLISHED_WAITING'
HSCR_JOINED = 'HSCR_JOINED'
HSSI_CONNECTING = 'HSSI_CONNECTING'
HSSI_ESTABLISHED = 'HSSI_ESTABLISHED'
HSSR_CONNECTING = 'HSSR_CONNECTING'
HSSR_JOINED = 'HSSR_JOINED'
class aiostem.structures.CircuitPurpose[source]

Bases: StrEnum

All possible purposes for circuits.

CIRCUIT_PADDING = 'CIRCUIT_PADDING'

Circuit kept open for padding.

CONFLUX_LINKED = 'CONFLUX_LINKED'

Linked conflux circuit.

CONFLUX_UNLINKED = 'CONFLUX_UNLINKED'

Unlinked conflux circuit.

CONTROLLER = 'CONTROLLER'

Circuit made by controller.

GENERAL = 'GENERAL'

General-purpose client.

HS_CLIENT_INTRO = 'HS_CLIENT_INTRO'

Hidden service client, connection to an introduction point.

HS_CLIENT_HSDIR = 'HS_CLIENT_HSDIR'

Hidden service client, fetching HS descriptor.

HS_CLIENT_REND = 'HS_CLIENT_REND'

Hidden service client, connection to a rendezvous point.

HS_SERVICE_INTRO = 'HS_SERVICE_INTRO'

Hidden service, introduction point.

HS_SERVICE_HSDIR = 'HS_SERVICE_HSDIR'

Hidden service, uploading HS descriptor.

HS_SERVICE_REND = 'HS_SERVICE_REND'

Hidden service, connection as a rendezvous point.

HS_VANGUARDS = 'HS_VANGUARDS'

Hidden service, pre-built vanguard circuit.

MEASURE_TIMEOUT = 'MEASURE_TIMEOUT'

Measuring circuit timeout.

PATH_BIAS_TESTING = 'PATH_BIAS_TESTING'

Path-bias testing circuit.

SERVER = 'SERVER'

A controller should never see these, actually.

TESTING = 'TESTING'

Testing circuit.

class aiostem.structures.CircuitStatus[source]

Bases: StrEnum

All possible statuses for a circuit.

LAUNCHED = 'LAUNCHED'

Circuit ID assigned to new circuit.

BUILT = 'BUILT'

All hops finished, can now accept streams.

GUARD_WAIT = 'GUARD_WAIT'

All hops finished, waiting to see if a circuit with a better guard will be usable.

EXTENDED = 'EXTENDED'

One more hop has been completed.

FAILED = 'FAILED'

Circuit closed (was not built).

CLOSED = 'CLOSED'

Circuit closed (was built).

class aiostem.structures.DescriptorPurpose[source]

Bases: StrEnum

All possible purposes for a descriptor.

CONTROLLER = 'controller'
GENERAL = 'general'
BRIDGE = 'bridge'
class aiostem.structures.Feature[source]

Bases: StrEnum

All known features Tor supports.

EXTENDED_EVENTS = 'EXTENDED_EVENTS'

Ask for extended information while receiving events.

VERBOSE_NAMES = 'VERBOSE_NAMES'

Replaces ServerID with LongName in events and GETINFO results.

class aiostem.structures.GuardEventStatus[source]

Bases: StrEnum

Possible statuses for a GUARD event.

NEW = 'NEW'

This node was not previously used as a guard.

Now we have picked it as one.

DROPPED = 'DROPPED'

This node is one we previously picked as a guard.

We no longer consider it to be a member of our guard list.

UP = 'UP'

The guard now seems to be reachable.

DOWN = 'DOWN'

The guard now seems to be unreachable.

BAD = 'BAD'

This node is now unusable as a guard.

Because of flags set in the consensus and/or values in the configuration.

BAD_L2 = 'BAD_L2'

This node is removed from the layer2 guard set.

This layer2 guard has expired or got removed from the consensus.

GOOD = 'GOOD'

This node is now usable as a guard.

Because of flags set in the consensus and/or values in the configuration.

class aiostem.structures.LivenessStatus[source]

Bases: StrEnum

Possible values for EventNetworkLiveness.status.

DOWN = 'DOWN'

Network or service is down.

UP = 'UP'

Network or service is up and running.

class aiostem.structures.LogSeverity[source]

Bases: StrEnum

Possible severities for all kind of log events.

DEBUG = 'DEBUG'
INFO = 'INFO'
NOTICE = 'NOTICE'
WARNING = 'WARN'
ERROR = 'ERROR'
class aiostem.structures.OrConnCloseReason[source]

Bases: StrEnum

All possible reasons why an OR connection is closed.

DONE = 'DONE'

The OR connection has shut down cleanly.

CONNECTREFUSED = 'CONNECTREFUSED'

We got an ECONNREFUSED while connecting to the target OR.

IDENTITY = 'IDENTITY'

We connected to the OR, but found that its identity was not what we expected.

CONNECTRESET = 'CONNECTRESET'

We got an ECONNRESET or similar IO error from the connection with the OR.

TIMEOUT = 'TIMEOUT'

We got an ETIMEOUT or similar IO error from the connection with the OR.

NOROUTE = 'NOROUTE'

We got an ENETUNREACH, EHOSTUNREACH, or similar error while connecting to the OR.

IOERROR = 'IOERROR'

We got some other IO error on our connection to the OR.

RESOURCELIMIT = 'RESOURCELIMIT'

We don’t have enough OS resources (file descriptors, etc.) to connect to the OR.

TLS_ERROR = 'TLS_ERROR'

Problem in TLS protocol.

MISC = 'MISC'

The OR connection closed for some other reason.

PT_MISSING = 'PT_MISSING'

No pluggable transport was available.

class aiostem.structures.OrConnStatus[source]

Bases: StrEnum

All possible statuses used in ORCONN.

NEW = 'NEW'

We have received a new incoming OR connection, and are starting the server handshake.

LAUNCHED = 'LAUNCHED'

We have launched a new outgoing OR connection, and are starting the client handshake.

CONNECTED = 'CONNECTED'

The OR connection has been connected and the handshake is done.

FAILED = 'FAILED'

Our attempt to open the OR connection failed.

CLOSED = 'CLOSED'

The OR connection closed in an unremarkable way.

class aiostem.structures.RemapSource[source]

Bases: StrEnum

All known remapping sources.

CACHE = 'CACHE'

Tor client decided to remap the address because of a cached answer.

EXIT = 'EXIT'

The remote node we queried gave us the new address as a response.

class aiostem.structures.RouterFlags[source]

Bases: StrEnum

All possible flags for an onion router.

AUTHORITY = 'Authority'

Is a directory authority.

BAD_EXIT = 'BadExit'

Is believed to be useless as an exit node

EXIT = 'Exit'

Supports commonly used exit ports.

FAST = 'Fast'

Is suitable for high-bandwidth circuits.

GUARD = 'Guard'

Is suitable for use as an entry guard.

HSDIR = 'HSDir'

Is considered a v2 hidden service directory.

MIDDLE_ONLY = 'MiddleOnly'

Is considered unsuitable for usage other than as a middle relay.

NO_ED_CONSENSUS = 'NoEdConsensus'

Any Ed25519 key in the descriptor does not reflect authority consensus.

STABLE = 'Stable'

Is suitable for long-lived circuits.

STALE_DESC = 'StaleDesc'

Should upload a new descriptor because the old one is too old.

RUNNING = 'Running'

Is currently usable over all its published ORPorts.

VALID = 'Valid'

Has been ‘validated’.

V2DIR = 'V2Dir'

Implements the v2 directory protocol or higher.

class aiostem.structures.Signal[source]

Bases: StrEnum

All possible signals that can be sent to Tor.

RELOAD = 'RELOAD'

Reload configuration items.

SHUTDOWN = 'SHUTDOWN'

Controlled shutdown, if server is an OP, exit immediately.

DUMP = 'DUMP'

Dump stats, log information about open connections and circuits.

DEBUG = 'DEBUG'

Debug, switch all open logs to log level debug.

HALT = 'HALT'

Immediate shutdown, clean up and exit now.

CLEARDNSCACHE = 'CLEARDNSCACHE'

Forget the client-side cached IP addresses for all host names.

NEWNYM = 'NEWNYM'

Switch to clean circuits, so new requests don’t share any circuits with old ones.

HEARTBEAT = 'HEARTBEAT'

Make Tor dump an unscheduled Heartbeat message to log.

DORMANT = 'DORMANT'

Tell Tor to become “dormant”.

ACTIVE = 'ACTIVE'

Tell Tor to stop being “dormant”.

class aiostem.structures.StreamClientProtocol[source]

Bases: StrEnum

All known client protocols for a stream.

SOCKS4 = 'SOCKS4'

Connecting using SocksV4.

SOCKS5 = 'SOCKS5'

Connecting using SocksV5.

TRANS = 'TRANS'

Transparent connections redirected by pf or netfilter.

NATD = 'NATD'

Transparent connections redirected by natd.

DNS = 'DNS'

DNS requests.

HTTPCONNECT = 'HTTPCONNECT'

HTTP CONNECT tunnel connections.

METRICS = 'METRICS'

Metrics query connections.

UNKNOWN = 'UNKNOWN'

Unknown client protocol type.

class aiostem.structures.StreamCloseReason[source]

Bases: StrEnum

All reasons provided to close a stream (as a string).

MISC = 'MISC'

Catch-all for unlisted reasons.

RESOLVEFAILED = 'RESOLVEFAILED'

Couldn’t look up hostname.

CONNECTREFUSED = 'CONNECTREFUSED'

Remote host refused connection.

EXITPOLICY = 'EXITPOLICY'

Relay refuses to connect to host or port.

DESTROY = 'DESTROY'

Circuit is being destroyed.

DONE = 'DONE'

Anonymized TCP connection was closed.

TIMEOUT = 'TIMEOUT'

Anonymized TCP connection was closed while connecting.

NOROUTE = 'NOROUTE'

Routing error while attempting to contact destination.

HIBERNATING = 'HIBERNATING'

Relay is temporarily hibernating.

INTERNAL = 'INTERNAL'

Internal error at the relay.

RESOURCELIMIT = 'RESOURCELIMIT'

Relay has no resources to fulfill request.

CONNRESET = 'CONNRESET'

Connection was unexpectedly reset.

TORPROTOCOL = 'TORPROTOCOL'

Sent when closing connection because of Tor protocol violations.

NOTDIRECTORY = 'NOTDIRECTORY'

Client sent RELAY_BEGIN_DIR to a non-directory relay.

PRIVATE_ADDR = 'PRIVATE_ADDR'

The client tried to connect to a private address like 127.0.0.1 or 10.0.0.1 over Tor.

END = 'END'

We received a RELAY_END message from the other side of this stream.

class aiostem.structures.StreamCloseReasonInt[source]

Bases: IntEnum

All reasons provided to close a stream.

MISC = 1

Catch-all for unlisted reasons.

RESOLVEFAILED = 2

Couldn’t look up hostname.

CONNECTREFUSED = 3

Remote host refused connection.

EXITPOLICY = 4

Relay refuses to connect to host or port.

DESTROY = 5

Circuit is being destroyed.

DONE = 6

Anonymized TCP connection was closed.

TIMEOUT = 7

Anonymized TCP connection was closed while connecting.

NOROUTE = 8

Routing error while attempting to contact destination.

HIBERNATING = 9

Relay is temporarily hibernating.

INTERNAL = 10

Internal error at the relay.

RESOURCELIMIT = 11

Relay has no resources to fulfill request.

CONNRESET = 12

Connection was unexpectedly reset.

TORPROTOCOL = 13

Sent when closing connection because of Tor protocol violations.

NOTDIRECTORY = 14

Client sent RELAY_BEGIN_DIR to a non-directory relay.

class aiostem.structures.StreamPurpose[source]

Bases: StrEnum

All known purposes for a stream.

DIR_FETCH = 'DIR_FETCH'

This stream is generated internally to Tor for fetching directory information.

DIR_UPLOAD = 'DIR_UPLOAD'

An internal stream for uploading information to a directory authority.

DIRPORT_TEST = 'DIRPORT_TEST'

A stream we’re using to test our own directory port to make sure it’s reachable.

DNS_REQUEST = 'DNS_REQUEST'

A user-initiated DNS request.

USER = 'USER'

This stream is handling user traffic.

I can also be internal to Tor, but it doesn’t match one of the other purposes.

class aiostem.structures.StreamStatus[source]

Bases: StrEnum

All possible statuses for a stream.

classmethod __bool__()

classes/types should always be True.

NEW = 'NEW'

New request to connect.

NEWRESOLVE = 'NEWRESOLVE'

New request to resolve an address.

REMAP = 'REMAP'

Address re-mapped to another.

SENTCONNECT = 'SENTCONNECT'

Sent a connect message along a circuit.

SENTRESOLVE = 'SENTRESOLVE'

Sent a resolve message along a circuit.

SUCCEEDED = 'SUCCEEDED'

Received a reply; stream established.

FAILED = 'FAILED'

Stream failed and not be retried.

CLOSED = 'CLOSED'

Stream closed.

DETACHED = 'DETACHED'

Detached from circuit; can still be retried.

CONTROLLER_WAIT = 'CONTROLLER_WAIT'

Waiting for controller to use ATTACHSTREAM.

XOFF_SENT = 'XOFF_SENT'

XOFF has been sent for this stream.

XOFF_RECV = 'XOFF_RECV'

XOFF has been received for this stream.

XON_SENT = 'XON_SENT'

XON has been sent for this stream.

XON_RECV = 'XON_RECV'

XON has been received for this stream.

Helper classes

These are annotated structures generally built from a single string.

class aiostem.structures.LongServerName[source]

A Tor Server name and its optional nickname.

fingerprint: Base16Bytes

Server fingerprint as a 20 bytes value.

nickname: str | None

Server nickname (optional).

__str__() str[source]

Get the string representation of this server.

Return type:

str

classmethod from_string(server: str) Self[source]

Build a new instance from a single string.

Returns:

Self – An instance of this class properly parsed from the provided string.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.PortPolicy[source]

A port policy for outgoing streams out of a router.

policy: Literal['accept', 'reject']

Type of policy (accept or reject).

ports: Annotated[Sequence[Annotated[int] | Annotated[PortRange]]]

List of ports or port ranges.

class aiostem.structures.PortRange[source]

Bases: GenericRange[Annotated[int, FieldInfo(annotation=NoneType, required=True, metadata=[Gt(gt=0), Lt(lt=65536)])]]

A range of ports.

min: RangeVal

Minimum value in the range (inclusive).

max: RangeVal

Maximum value in the range (inclusive).

class aiostem.structures.RouterStatus[source]

Router status V3 item.

flags: Set[Annotated[RouterFlags | str]]

Router status flags describing router properties.

nickname: str

Server nickname.

identity: Annotated[bytes]

Unique router fingerprint.

digest: Annotated[bytes]

Hash of its most recent descriptor as signed.

ip: IPv4Address

Current IPv4 address.

or_port: int

Current onion routing port.

dir_port: Annotated[int | None]

Optional directory port.

addresses: Sequence[TcpAddressPort] | None

Other known onion routing addresses

port_policy: PortPolicy | None

Port policy for outgoing streams.

bandwidth: int | None

An estimate of the bandwidth of this relay (in KB/s).

bw_measured: int | None

Measured bandwidth currently produced by measuring stream capacities.

bw_unmeasured: bool | None

Bandwidth value is not based on a threshold of 3 or more measurements.

class aiostem.structures.StreamTarget[source]

Describe the target of a stream.

host: IPv4Address | IPv6Address | str

Target server for the stream.

node: LongServerName | None

Exit node (if any).

port: Annotated[int]

Target port.

class aiostem.structures.TcpAddressPort[source]

Describe a TCP target with a host and a port.

host: AnyAddress

Target host for the TCP connection.

port: AnyPort

Target port for the TCP connection.

__str__() str[source]

Get the string representation of this connection.

Return type:

str

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.VersionRange[source]

A range of versions numbers.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.VirtualPortTarget[source]

Target for an onion virtual port.

port: Annotated[int]

Virtual port to listen to on a hidden service.

target: TcpAddressPort

Local target for this virtual port.

aiostem.structures.VirtualPort

A virtual port parser and serializer from/to a VirtualPortTarget.

alias of Annotated[VirtualPortTarget, TrBeforeStringSplit(maxsplit=1, separator=,, dict_keys=(‘port’, ‘target’), when_used=always)]

Ed25519 certificates

class aiostem.structures.Ed25519Certificate[source]

Bases: ABC, BaseModel

Tor’s representation of an ed25519 certificate.

version: PositiveInt

Version of the certificate as used by Tor.

abstractmethod classmethod bytes_to_mapping(value: bytes) Mapping[str, Any][source]

Build a new instance from bytes.

Return type:

Mapping[str, Any]

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.Ed25519CertificateV1[source]

Bases: Ed25519Certificate

Version 1 of tor’s representation of an ed25519 certificate.

ED25519_KEY_LENGTH: ClassVar[int] = 32

Length of the Ed25519 public key.

ED25519_SIGNATURE_LENGTH: ClassVar[int] = 64

Length of the Ed25519 signature.

version: Literal[1]

Version of the certificate as used by Tor.

purpose: Ed25519CertPurpose

Purpose of this ed25519 certificate.

expiration: DatetimeUTC

Expiration date for this certificate.

key: Ed25519PublicKeyBase64 | None

Ed25519 public key.

extensions: Sequence[Ed25519CertExtension]

List of ed25519 extensions used along with this certificate.

signature: Base64Bytes

Ed25519 certificate signature.

signed_content: Base64Bytes

Raw content of everything covered by the signature.

classmethod bytes_to_mapping(data: bytes) Mapping[str, Any][source]

Build a new instance from bytes.

Return type:

Mapping[str, Any]

property can_validate: bool

Whether this certificate can be validated.

This returns False when any extension we do not understand has a AFFECTS_VALIDATION flag.

property expired: bool

Tell whether this certificate has expired.

property signing_key: Ed25519PublicKey | None

Get the signing key used with this certificate.

This works by looking up for this key in the parsed extensions. This key can then be used to check for this certificate’s signature.

Returns:

The public key used to verify this certificate, if any.

raise_for_invalid_signature(key: Ed25519PublicKey) None[source]

Check this certificate’s signature.

Parameters:

key (Ed25519PublicKey) – A public key to check this certificate against.

Raises:

CryptographyError – When the signature is invalid.

Return type:

None

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.Ed25519CertPurpose[source]

Bases: IntEnum

All types of ed25519 certificates.

Link key certificate certified by RSA1024 identity.

IDENTITY = 2

RSA1024 Identity certificate, self-signed.

AUTHENTICATE = 3

RSA1024 AUTHENTICATE cell link certificate, signed with RSA1024 key.

ED25519_SIGNING = 4

Ed25519 signing key, signed with identity key.

TLS link certificate signed with ed25519 signing key.

ED25519_AUTHENTICATE = 6

Ed25519 AUTHENTICATE cell key, signed with ed25519 signing key.

ED25519_IDENTITY = 7

Ed25519 identity, signed with RSA identity.

HS_V3_DESC_SIGNING = 8

Hidden service V3 signing key.

HS_V3_INTRO_AUTH = 9

Hidden service V3 intro authentication key.

NTOR_ONION_KEY = 10

ntor-onion-key-crosscert in a server descriptor.

HS_V3_NTOR_ENC = 11

Cross-certification of the encryption key using the descriptor signing key.

class aiostem.structures.Ed25519CertExtensionFlags[source]

Bases: IntFlag

Available flags on a Ed25519CertExtension.

AFFECTS_VALIDATION = 1

The extension affects whether the certificate is valid.

class aiostem.structures.Ed25519CertExtensionType[source]

Bases: IntEnum

Available types of Ed25519CertExtension.

HAS_SIGNING_KEY = 4

There is a signing key bundled with this certificate.

class aiostem.structures.BaseEd25519CertExtension[source]

Bases: ABC, BaseModel

Describe a single ed25519 certificate extension.

type: Ed25519CertExtensionType | NonNegativeInt

Type of the current extension.

flags: Ed25519CertExtensionFlags

Set of flags for this extension.

classmethod bytes_to_mapping_list(raw: bytes) Sequence[Mapping[str, Any]][source]

Parse and extract extension structures from raw.

Return type:

Sequence[Mapping[str, Any]]

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.Ed25519CertExtensionSigningKey[source]

Bases: BaseEd25519CertExtension

Describe an unknown ed25519 certificate extension.

type: Literal[Ed25519CertExtensionType.HAS_SIGNING_KEY]

Type of extension.

key: Ed25519PublicKeyBase64

Public ed25519 signing key as part of this extension.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.Ed25519CertExtensionUnkown[source]

Bases: BaseEd25519CertExtension

Describe an unknown ed25519 certificate extension.

data: Base64Bytes

Raw data for this mysterious unknown extension.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

Hidden services

class aiostem.structures.BaseHiddenServiceAddress[source]

Bases: str

Base class for all hidden service addresses.

ADDRESS_LENGTH: ClassVar[int]

Length of the address without the top-level domain.

ADDRESS_PATTERN: ClassVar[str]

Regular expression pattern used to match the address.

ADDRESS_SUFFIX: ClassVar[str] = '.onion'

Suffix and top-level domain for onion addresses.

ADDRESS_SUFFIX_LENGTH: ClassVar[int] = 6

Length of the onion suffix.

VERSION: ClassVar[HiddenServiceVersion]

Hidden service version for the current address.

classmethod strip_suffix(address: str) str[source]

Strip the domain suffix from the provided string.

Parameters:

address (str) – a raw string encoding a hidden service address

Returns:

str – The address without its .onion suffix.

class aiostem.structures.HiddenServiceAddressV2[source]

Bases: BaseHiddenServiceAddress

Represent a V2 hidden service.

ADDRESS_LENGTH: ClassVar[int] = 16

Length of the address without the top-level domain.

ADDRESS_PATTERN: ClassVar[str] = '^[a-z2-7]{16}([.]onion)?$'

Regular expression pattern used to match the address.

VERSION: ClassVar[HiddenServiceVersion] = 2

Hidden service version for the current address.

classmethod from_string(domain: str) Self[source]

Build from a user string.

Parameters:

domain (str) – A valid .onion domain, with or without its TLD.

Returns:

Self – A valid V2 domain without its .onion suffix.

class aiostem.structures.HiddenServiceAddressV3[source]

Bases: BaseHiddenServiceAddress

Represent a V3 hidden service.

ADDRESS_LENGTH: ClassVar[int] = 56

Length of the address without the top-level domain.

ADDRESS_PATTERN: ClassVar[str] = '^[a-z2-7]{56}([.]onion)?$'

Regular expression pattern used to match the address.

VERSION: ClassVar[HiddenServiceVersion] = 3

Hidden service version for the current address.

classmethod from_string(domain: str) Self[source]

Build from a user string.

Parameters:

domain (str) – A valid .onion domain, with or without its TLD.

Raises:

PydanticCustomError – On invalid onion V3 domain.

Returns:

Self – A valid V3 domain without its .onion suffix.

property public_key: Ed25519PublicKey

Get the ed25519 public key for this domain.

Returns:

The ed25519 public key associated with this v3 onion domain.

aiostem.structures.HiddenServiceAddress

Any kind of onion service address.

alias of Annotated[Annotated[HiddenServiceAddressV2, Tag(tag=HiddenServiceVersion.ONION_V2)] | Annotated[HiddenServiceAddressV3, Tag(tag=HiddenServiceVersion.ONION_V3)], Discriminator(discriminator=_discriminate_hidden_service_version, custom_error_type=None, custom_error_message=None, custom_error_context=None)]

class aiostem.structures.HiddenServiceVersion[source]

Bases: IntEnum

Any valid onion hidden service version.

ONION_V2 = 2
ONION_V3 = 3
class aiostem.structures.HsDescBase[source]

Hidden service descriptor base class.

ADAPTER: ClassVar[TypeAdapter[Self] | None] = None

Cached adapter used while deserializing the message.

classmethod adapter() TypeAdapter[Self][source]

Get a cached type adapter to deserialize this object.

Return type:

TypeAdapter[Self]

class aiostem.structures.HsDescV2[source]

Bases: HsDescBase

Hidden service descriptor for v2 onions.

INTROS_ADAPTER: ClassVar[TypeAdapter[Sequence[HsIntroPointV2]]] = TypeAdapter(Sequence[HsIntroPointV2])

Adapter used to list introduction points.

descriptor_id: Annotated[bytes]

Periodically changing identifier of 160 bits.

version: Annotated[int]

The version number of this descriptor’s format.

permanent_key: Annotated[RSAPublicKey]

Permanent public RSA key linked to this onion service.

secret_id_part: Annotated[bytes]

Secret id so we can verify that the signed descriptor belongs to “descriptor-id”.

published: Annotated[datetime]

A timestamp when this descriptor has been created.

protocol_versions: Annotated[Set[int]]

A comma-separated list of recognized and permitted version numbers.

For use in INTRODUCE cells.

introduction_points_bytes: Annotated[bytes]

Content of the introduction points.

computed_digest: Annotated[bytes]

Computed digest of this descriptor (everything except the signature).

This field is computed and not part of the original descriptor. It is used to check the signature against the permanent_key.

signature: Annotated[bytes]

A signature of all fields with the service’s private key.

introduction_points(auth_cookie: HsDescAuthCookie | None = None) Sequence[HsIntroPointV2][source]

Parse introduction points for this descriptor.

Note that decryption is not implemented and will probably never be since onion v2 has been deprecated for a long time now. Instead it raises NotImplementedError.

Parameters:

auth_cookie (HsDescAuthCookie | None, default: None) – Optional authentication cookie used to decrypt introduction points.

Raises:

NotImplementedError – When auth_cookie is not None.

Returns:

Sequence[HsIntroPointV2] – A list of introduction points used in this descriptor.

classmethod text_to_mapping(body: str) Mapping[str, Any][source]

Parse body to a raw descriptor to mapping.

Parameters:

body (str) – The content of the descriptor.

Returns:

Mapping[str, Any] – A map suitable for parsing from pydantic.

classmethod from_text(body: str) Self[source]

Build a HsDescV2 object from a text descriptor.

Parameters:

body (str) – The content of the descriptor.

Returns:

Self – A parsed descriptor.

raise_for_invalid_signature() None[source]

Check the provided signature.

This does not use cryptography’s signature mechanism since Tor seems to have a specific signature method, not implemented by cryptography.

An issue was opened by stem on this matter:
Raises:

CryptographyError – When the certificate is improperly signed.

Returns:

None – Whether the signature is correct for the current descriptor.

class aiostem.structures.HsDescV3[source]

Bases: HsDescBase

Hidden service descriptor for v3 onions.

SIGNATURE_PREFIX: ClassVar[bytes] = b'Tor onion service descriptor sig v3'

Prefix used while checking the signature of this descriptor.

hs_descriptor: Annotated[int]

The version number of this descriptor’s format.

revision: Annotated[int]

The revision number of the descriptor.

lifetime: Annotated[timedelta]

The lifetime of a descriptor in minutes.

signing_cert: Annotated[Ed25519CertificateV1]

Ed25519 certificate used to validate this descriptor.

superencrypted: Annotated[bytes]

Encrypted content of the descriptor.

This contains the first layer (or outer layer). This can simply be decrypted with the name of the hidden service this descriptor is created for.

signature: Annotated[bytes]

A signature of all fields with the service’s private key.

signed_content: Annotated[bytes]

Raw content of everything covered by the signature.

classmethod text_to_mapping(body: str) Mapping[str, Any][source]

Parse the body of a raw descriptor to a mapping.

Parameters:

body (str) – The content of the descriptor.

Returns:

Mapping[str, Any] – A map suitable for parsing from pydantic.

classmethod from_text(body: str) Self[source]

Build a HsDescV3 object from a text descriptor.

Parameters:

body (str) – The content of the descriptor.

Returns:

Self – A parsed descriptor.

decrypt_layer1(address: HiddenServiceAddressV3) HsDescV3Layer1[source]

Decrypt the descriptor’s first layer using the onion address.

Parameters:

address (HiddenServiceAddressV3) – The hidden service v3 address.

Raises:
Returns:

HsDescV3Layer1 – A layer1 object, containing additional data.

decrypt_layer2(address: HiddenServiceAddressV3, client: X25519PrivateKey | None = None) HsDescV3Layer2[source]

Decrypt the descriptor’s second layer using the onion address.

Parameters:
Raises:
Returns:

HsDescV3Layer2 – A layer2 object, containing additional data.

get_subcred(address: HiddenServiceAddressV3) bytes[source]

Get the computed sub-credential bytes used decrypt layers.

Parameters:

address (HiddenServiceAddressV3) – Hidden service v3 address.

Raises:

ReplySyntaxError – When the descriptor does not have a signing key.

Returns:

bytes – Computed digest used as sub-credential.

raise_for_invalid_signature() None[source]

Check that this descriptor is properly signed.

This is checked against signing_cert.

Return type:

None

class aiostem.structures.HsDescV3Layer[source]

Bases: ABC, HsDescBase

Base class for both layers in a hidden service v3 descriptor.

CONSTANT: ClassVar[bytes]

Constant used while creating the decryption key material.

ENC_SALT_LEN: ClassVar[int] = 16

Salt length at the beginning of the encrypted blob.

ENC_MAC_LEN: ClassVar[int] = 32

Message authentication code length at the end of the encrypted blob.

SEC_KEY_LEN: ClassVar[int] = 32

Length of the AES key in the computed secret material.

SEC_IV_LEN: ClassVar[int] = 16

Length of the IV in the computed secret material.

SEC_MAC_LEN: ClassVar[int] = 32

Length of the MAC from the computed secret material.

SEC_TOTAL_LEN: ClassVar[int] = 80

Total length of the secret material.

classmethod decrypt_layer(desc: HsDescV3, address: HiddenServiceAddressV3, blob: bytes, cookie: bytes = b'') Self[source]

Decrypt the provided cipher using the provided material.

Parameters:
  • desc (HsDescV3) – Hidden service v3 descriptor this layer is attached to.

  • address (HiddenServiceAddressV3) – Hidden service v3 address the descriptor is related to.

  • blob (bytes) – Raw bytes of the cipher we want to decrypt.

  • cookie (bytes, default: b'') – Additional bytes to add in the mix of secret_data.

Raises:
Returns:

Self – An instance of this layer.

abstractmethod classmethod text_to_mapping(body: str) Mapping[str, Any][source]

Parse the body of a raw layer to a mapping.

Return type:

Mapping[str, Any]

classmethod from_text(body: str) Self[source]

Build a layer object from decrypted text content.

Parameters:

body (str) – The layer content as raw text.

Returns:

Self – A parsed layer.

class aiostem.structures.HsDescV3Layer1[source]

Bases: HsDescV3Layer

First layer decrypted from a hidden service v3 (outer layer).

AUTH_KEY_KEN: ClassVar[int] = 32

Length of the AES key used to decrypt the authentication cookie.

CLIENT_ID_LEN: ClassVar[int] = 8

Length of the client identifier.

AUTH_KEYS_TOTAL_LEN: ClassVar[int] = 40

Total length of the keys used to decrypt the authentication cookie.

CONSTANT: ClassVar[bytes] = b'hsdir-superencrypted-data'

Constant used while creating the decryption key material.

auth_key_type: OnionClientAuthKeyType

Key type for client authentication.

auth_ephemeral_key: Annotated[X25519PublicKey]

Ephemeral x25519 public key generated by the hidden service.

auth_clients: Sequence[Annotated[HsDescV3AuthClient]]

List of authentication clients.

encrypted: Annotated[bytes]

Encrypted content of the layer.

This contains the second layer (or inner layer).

classmethod from_descriptor(desc: HsDescV3, address: HiddenServiceAddressV3) Self[source]

Build the layer from a hidden service v3 descriptor.

Parameters:
Returns:

Self – An instance of this layer.

classmethod text_to_mapping(body: str) Mapping[str, Any][source]

Parse the body of a raw layer1 to a mapping.

Parameters:

body (str) – The decrypted content of the layer.

Returns:

Mapping[str, Any] – A map suitable for parsing from pydantic.

Find and decrypt the authentication cookie so we can then decrypt the second layer.

Parameters:
Raises:

CryptographyError – When no authentication client matches the provided key.

Returns:

bytes – The decrypted authentication cookie.

class aiostem.structures.HsDescV3Layer2[source]

Bases: HsDescV3Layer

Second layer decrypted from a hidden service v3 (inner layer).

CONSTANT: ClassVar[bytes] = b'hsdir-encrypted-data'

Constant used while creating the decryption key material.

flow_control: Annotated[HsDescV3FlowControl] | None = None

Flow control protocol version and congestion value (proposal 324).

pow_params: Annotated[HsDescV3PowParams] | None = None

Proof of work parameters used when contacting the service.

formats: Annotated[set[Annotated[int]]]

CREATE2 cell format numbers that the server recognizes.

introduction_auth: Annotated[set[str]] | None = None

List of introduction-layer authentication types.

A client that does not support at least one of these authentication types will not be able to contact the host.

introduction_points: Sequence[HsIntroPointV3]

List of introduction points used to connect to this hidden service.

single_service: bool = False

Whether this service is a single onion service (see proposal 260).

classmethod from_descriptor(desc: HsDescV3, address: HiddenServiceAddressV3, client: X25519PrivateKey | None = None) Self[source]

Build the layer from a hidden service v3 descriptor.

Parameters:
Returns:

Self – An instance of this layer.

classmethod text_to_mapping(body: str) Mapping[str, Any][source]

Parse the body of a raw layer2 to a mapping.

Parameters:

body (str) – The decrypted content of the layer.

Returns:

Mapping[str, Any] – A map suitable for parsing from pydantic.

class aiostem.structures.HsDescAction[source]

Bases: StrEnum

Possible actions in a HS_DESC event.

CREATED = 'CREATED'
FAILED = 'FAILED'
IGNORE = 'IGNORE'
RECEIVED = 'RECEIVED'
REQUESTED = 'REQUESTED'
UPLOAD = 'UPLOAD'
UPLOADED = 'UPLOADED'
class aiostem.structures.HsDescAuthCookie[source]

Bases: BaseModel

An authentication cookie used for onion v2.

Length of the random key generated here.

Length of the base64 value without the useless padding.

Length of the base64 value with the useless padding.

auth_type: Literal[HsDescAuthTypeInt.BASIC_AUTH, HsDescAuthTypeInt.STEALTH_AUTH]

Allowed values describing the type of authentication cookie we have.

cookie: bytes

Raw cookie value as 16 random bytes.

classmethod from_string(value: str) Self[source]

Get the bytes from a standard string.

Return type:

Self

classmethod from_bytes(value: bytes) Self[source]

Build a new instance from raw bytes.

Return type:

Self

classmethod generate(auth_type: Literal[HsDescAuthTypeInt.BASIC_AUTH, HsDescAuthTypeInt.STEALTH_AUTH]) Self[source]

Generate a new authentication cookie.

Return type:

Self

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class aiostem.structures.HsDescAuthTypeInt[source]

Bases: IntEnum

Integer values for HsDescAuthTypeStr.

NO_AUTH = 0
BASIC_AUTH = 1
STEALTH_AUTH = 2
class aiostem.structures.HsDescAuthTypeStr[source]

Bases: StrEnum

Possible values for AuthType in a HS_DESC event.

BASIC_AUTH = 'BASIC_AUTH'
NO_AUTH = 'NO_AUTH'
STEALTH_AUTH = 'STEALTH_AUTH'
UNKNOWN = 'UNKNOWN'
class aiostem.structures.HsDescClientAuth[source]

Bases: object

Client authentication for onion v2.

name: str

Client name for this authentication.

cookie: HsDescAuthCookie | None

The authentication cookie, generated by Tor when None.

aiostem.structures.HsDescClientAuthV2

Annotated structure for hidden service v2 client authentication.

alias of Annotated[HsDescClientAuth, TrBeforeStringSplit(maxsplit=1, separator=:, dict_keys=(‘name’, ‘cookie’), when_used=always)]

aiostem.structures.HsDescClientAuthV3

Annotated structure for hidden service v3 client authentication.

alias of Annotated[X25519PublicKey, TrX25519PublicKey(), EncodedBytes(encoder=Base32Encoder, when_used=always)]

class aiostem.structures.HsDescFailReason[source]

Bases: StrEnum

Possible values for REASON in a HS_DESC event.

BAD_DESC = 'BAD_DESC'

Descriptor was retrieved, but found to be unparsable.

NOT_FOUND = 'NOT_FOUND'

HS descriptor with given identifier was not found.

QUERY_NO_HSDIR = 'QUERY_NO_HSDIR'

No suitable HSDir were found for the query.

QUERY_RATE_LIMITED = 'QUERY_RATE_LIMITED'

Query for this service is rate-limited.

QUERY_REJECTED = 'QUERY_REJECTED'

Query was rejected by HS directory.

UNEXPECTED = 'UNEXPECTED'

Nature of failure is unknown.

UPLOAD_REJECTED = 'UPLOAD_REJECTED'

Descriptor was rejected by HS directory.

class aiostem.structures.HsDescV3AuthClient[source]

Bases: object

Entry for a single authenticated client on HsDescV3.

Note

When client authentication is not enabled, these values are populated with random values.

client_id: Annotated[bytes]

Unique client identifier (8 bytes).

iv: Annotated[bytes]

Initialization vector (16 bytes).

Descriptor cookie cipher-text (16 bytes).

Decrypt the encrypted cookie with the provided key.

Parameters:

key (bytes) – The AES key needed to decrypt this cookie.

Returns:

bytes – A decrypted version of the authentication cookie.

class aiostem.structures.HsDescV3FlowControl[source]

Bases: object

Flow and congestion control for a hidden service.

version_range: Annotated[VersionRange]

Range of supported flow control versions.

sendme_inc: Annotated[int]

Comes from the service’s current cc_sendme_inc consensus parameter.

class aiostem.structures.HsDescV3PowParams[source]

Bases: object

PoW parameters as parsed from a hidden service v3 descriptor.

type: str

The type of PoW system used.

seed: Annotated[bytes]

A random seed that should be used as the input to the PoW hash function.

suggested_effort: Annotated[int]

An effort value that clients should aim for when contacting the service.

expiration: Annotated[datetime]

A timestamp after which the above seed expires.

class aiostem.structures.HsIntroPointV2[source]

Bases: HsDescBase

A single introduction point for a v2 descriptor.

introduction_point: Annotated[bytes]

The identifier of this introduction point.

ip: IPv4Address

The IP address of this introduction point.

onion_port: Annotated[int]

The TCP port on which the introduction point is listening for incoming requests.

onion_key: Annotated[RSAPublicKey]

The public key that can be used to encrypt messages to this introduction point.

service_key: Annotated[RSAPublicKey]

The public key that can be used to encrypt messages to the hidden service.

classmethod text_to_mapping_list(body: str) Sequence[Mapping[str, Any]][source]

Parse body to a list of raw introduction points mappings.

Parameters:

body (str) – The raw content of the descriptors.

Returns:

Sequence[Mapping[str, Any]] – A list of mappings for introduction points.

class aiostem.structures.HsIntroPointV3[source]

Bases: HsDescBase

A single introduction point for a v3 descriptor.

Location and identities of introduction point nodes.

These are automatically parsed from bytes as provided by the second layer.

ntor_onion_key: Annotated[X25519PublicKey]

Key of the introduction point Tor node used for the ntor handshake.

auth_key_cert: Annotated[Ed25519CertificateV1]

Contains the introduction authentication key.

enc_key: Annotated[X25519PublicKey]

Public key used to encrypt the introduction request to service.

enc_key_cert: Annotated[Ed25519CertificateV1]

Cross-certification of the encryption key using the descriptor signing key.

classmethod text_to_mapping_list(body: str) Sequence[Mapping[str, Any]][source]

Parse body to a list of raw introduction points mappings.

Parameters:

body (str) – The raw content of the descriptors.

Returns:

Sequence[Mapping[str, Any]] – A list of mappings for introduction points.

class aiostem.structures.OnionClientAuthKeyStruct[source]

Intermediate structure used to parse a key for an authorized client.

auth_type: OnionClientAuthKeyType

Type of key we are about to parse.

data: Annotated[bytes]

Data bytes for the provided key.

class aiostem.structures.OnionClientAuth[source]

A client key attached to a single onion domain.

address: Annotated[Annotated[HiddenServiceAddressV2] | Annotated[HiddenServiceAddressV3]]

Hidden service address without the .onion suffix.

key: Annotated[Annotated[X25519PrivateKey] | Annotated[OnionClientAuthKeyStruct]]

Client’s private x25519 key.

name: str | None

Client name (optional).

flags: Annotated[Set[OnionClientAuthFlags]]

Flags associated with this client.

class aiostem.structures.OnionClientAuthFlags[source]

Bases: StrEnum

List of flags attached to a running onion service.

PERMANENT = 'Permanent'

This client’s credentials should be stored on the file system.

class aiostem.structures.OnionClientAuthKeyType[source]

Bases: StrEnum

All types of keys for onion client authentication.

X25519 = 'x25519'
class aiostem.structures.OnionServiceFlags[source]

Bases: StrEnum

Available flag options for command ADD_ONION.

DISCARD_PK = 'DiscardPK'

The server should not include the newly generated private key as part of the response.

DETACH = 'Detach'

Do not associate the newly created Onion Service to the current control connection.

BASIC_AUTH = 'BasicAuth'

Client authorization is required using the “basic” method (v2 only).

V3AUTH = 'V3Auth'

Version 3 client authorization is required (v3 only).

NON_ANONYMOUS = 'NonAnonymous'

Add a non-anonymous Single Onion Service.

MAX_STREAMS_CLOSE_CIRCUIT = 'MaxStreamsCloseCircuit'

Close the circuit is the maximum streams allowed is reached.

class aiostem.structures.OnionServiceKeyType[source]

Bases: StrEnum

All types of keys for onion services.

RSA1024 = 'RSA1024'

The server should use the 1024 bit RSA key provided in as KeyBlob (v2).

ED25519_V3 = 'ED25519-V3'

The server should use the ed25519 v3 key provided in as KeyBlob (v3).

class aiostem.structures.OnionServiceKeyStruct[source]

Intermediate structure used to parse a key for an onion service.

key_type: OnionServiceKeyType

Type of key we are about to use.

data: Annotated[bytes]

Data bytes for the provided key.

class aiostem.structures.OnionServiceNewKeyStruct[source]

Structure used to parse any new KEY.

key_type: OnionServiceKeyType | Literal['BEST']

Type of key we want to generate.

prefix: Literal['NEW']

Common prefix for all new keys.

Reply data

These are directly part of the replies when a command has been successful.

class aiostem.structures.ReplyDataAddOnion[source]

Reply data linked to a successful ADD_ONION command.

See also

address: HiddenServiceAddressV3

Called ServiceID in the documentation, this is the onion address.

client_auth: Sequence[Annotated[HsDescClientAuth]]

List of client authentication for a v2 address.

client_auth_v3: Sequence[Annotated[X25519PublicKey]]

List of client authentication for a v3 address.

key: Annotated[Annotated[RSAPrivateKey] | Annotated[Ed25519PrivateKey] | Annotated[OnionServiceKeyStruct]] | None

Onion service key.

class aiostem.structures.ReplyDataAuthChallenge[source]

Reply data linked to a successful AUTHCHALLENGE command.

client_nonce: Annotated[bytes] | str | None

Not part of the response, but it is very nice to have it here.

This eases the handling of cryptography routines used to check hashes.

server_hash: Annotated[bytes]

Server hash as computed by the server.

server_nonce: Annotated[bytes]

Server nonce as provided by the server.

build_client_hash(cookie: bytes, client_nonce: str | bytes | None = None) bytes[source]

Build a token suitable for authentication.

Parameters:
Raises:

CryptographyError – When our client nonce is None.

Returns:

bytes – A value that you can authenticate with.

build_server_hash(cookie: bytes, client_nonce: str | bytes | None = None) bytes[source]

Recompute the server hash.

Parameters:
Raises:

CryptographyError – When our client nonce is None.

Returns:

bytes – The same value as in server_hash if everything went well.

raise_for_server_hash_error(cookie: bytes, client_nonce: str | bytes | None = None) None[source]

Check that our server hash is consistent with what we compute.

Parameters:
Raises:

CryptographyError – When our server nonce does not match the one we computed.

Return type:

None

class aiostem.structures.ReplyDataExtendCircuit[source]

Reply data linked to a successful EXTENDCIRCUIT command.

circuit: int

Build or extended circuit.

class aiostem.structures.ReplyDataMapAddressItem[source]

A single reply data associated for a successful MAPADDRESS command.

original: AnyHost | None

Original address to replace with another one.

replacement: AnyHost | None

Replacement item for the corresponding original address.

class aiostem.structures.ReplyDataOnionClientAuthView[source]

Reply data linked to a successful ONION_CLIENT_AUTH_VIEW command.

address: HiddenServiceAddressV3 | None

Onion address minus the .onion suffix.

clients: Sequence[OnionClientAuth]

List of authorized clients and their private key.

class aiostem.structures.ReplyDataProtocolInfo[source]

Reply data linked to a successful PROTOCOLINFO command.

auth_methods: Annotated[Set[AuthMethod]]

List of available authentication methods.

Path on the server to the cookie file.

protocol_version: int

Version of the Tor control protocol in use.

tor_version: str

Version of Tor.

General status

class aiostem.structures.StatusActionGeneral[source]

Bases: StrEnum

Possible actions for a STATUS_GENERAL event.

Note

BAD_LIBEVENT has been removed since Tor 0.2.7.1.

BUG = 'BUG'

Tor has encountered a situation that its developers never expected.

See also

StatusGeneralBug

DIR_ALL_UNREACHABLE = 'DIR_ALL_UNREACHABLE'

Tor believes that none of the known directory servers are reachable.

CLOCK_JUMPED = 'CLOCK_JUMPED'

Tor spent enough time without CPU cycles that it has closed all its circuits.

CLOCK_SKEW = 'CLOCK_SKEW'

A lock skew has been detected by Tor.

DANGEROUS_VERSION = 'DANGEROUS_VERSION'

Tor has found that directory servers don’t recommend its version of the Tor software.

TOO_MANY_CONNECTIONS = 'TOO_MANY_CONNECTIONS'

Tor has reached its ulimit -n on file descriptors or sockets.

class aiostem.structures.StatusGeneralBug[source]

Arguments for action StatusActionGeneral.BUG.

reason: str

Tell why we got a general status report for a bug.

class aiostem.structures.StatusGeneralClockJumped[source]

Arguments for action StatusActionGeneral.CLOCK_JUMPED.

time: Annotated[timedelta]

Duration Tor thinks it was unconscious for (or went back in time).

class aiostem.structures.StatusGeneralClockSkew[source]

Arguments for action StatusActionGeneral.CLOCK_SKEW.

skew: Annotated[timedelta]

Estimate of how far we are from the time declared in the source.

source: Annotated[ClockSkewSource]

Source of the clock skew event.

class aiostem.structures.StatusGeneralDangerousVersionReason[source]

Bases: StrEnum

All reasons why we can get a dangerous version notice.

NEW = 'NEW'
OBSOLETE = 'OBSOLETE'
RECOMMENDED = 'RECOMMENDED'
class aiostem.structures.StatusGeneralDangerousVersion[source]

Arguments for action StatusActionGeneral.DANGEROUS_VERSION.

current: str

Current running version.

reason: StatusGeneralDangerousVersionReason

Tell why is this a dangerous version.

recommended: Annotated[Set[str]]

List of recommended versions to use instead.

class aiostem.structures.StatusGeneralTooManyConnections[source]

Arguments for action StatusActionGeneral.TOO_MANY_CONNECTIONS.

current: Annotated[int]

Number of currently opened file descriptors.

Client status

These dataclass() structures are specific for each action of each event.

class aiostem.structures.StatusActionClient[source]

Bases: StrEnum

Possible actions for a STATUS_CLIENT event.

BOOTSTRAP = 'BOOTSTRAP'

Tor has made some progress at establishing a connection to the Tor network.

CIRCUIT_ESTABLISHED = 'CIRCUIT_ESTABLISHED'

Tor is able to establish circuits for client use.

CIRCUIT_NOT_ESTABLISHED = 'CIRCUIT_NOT_ESTABLISHED'

We are no longer confident that we can build circuits.

CONSENSUS_ARRIVED = 'CONSENSUS_ARRIVED'

Tor has received and validated a new consensus networkstatus.

DANGEROUS_PORT = 'DANGEROUS_PORT'

A stream was initiated to a port that’s commonly used for vuln-plaintext protocols.

DANGEROUS_SOCKS = 'DANGEROUS_SOCKS'

A connection was made to Tor’s SOCKS port without support for hostnames.

ENOUGH_DIR_INFO = 'ENOUGH_DIR_INFO'

Tor now knows enough network-status documents and enough server descriptors.

NOT_ENOUGH_DIR_INFO = 'NOT_ENOUGH_DIR_INFO'

We fell below the desired threshold directory information.

SOCKS_BAD_HOSTNAME = 'SOCKS_BAD_HOSTNAME'

Some application gave us a funny-looking hostname.

SOCKS_UNKNOWN_PROTOCOL = 'SOCKS_UNKNOWN_PROTOCOL'

A connection was made to Tor’s SOCKS port and did not speak the SOCKS protocol.

class aiostem.structures.StatusClientBootstrap[source]

Arguments for action StatusActionClient.BOOTSTRAP.

progress: Annotated[int]

A number between 0 and 100 for how far through the bootstrapping process we are.

summary: str

Describe the next task that Tor will tackle.

tag: str

A string that controllers can use to recognize bootstrap phases.

count: Annotated[int] | None

Tells how many bootstrap problems there have been so far at this phase.

host: Annotated[bytes] | None

The identity digest of the node we’re trying to connect to.

hostaddr: TcpAddressPort | None

An address and port combination, where ‘address’ is an ipv4 or ipv6 address.

reason: str | None

Lists one of the reasons allowed in the ORCONN event.

recommendation: Literal['ignore', 'warn'] | None

Either “ignore” or “warn” as a recommendation.

warning: str | None

Any hints Tor has to offer about why it’s having troubles bootstrapping.

class aiostem.structures.StatusClientCircuitNotEstablished[source]

Arguments for action StatusActionClient.CIRCUIT_ESTABLISHED.

reason: Literal['CLOCK_JUMPED', 'DIR_ALL_UNREACHABLE', 'EXTERNAL_ADDRESS']

Which other status event type caused our lack of confidence.

class aiostem.structures.StatusClientDangerousPort[source]

Arguments for action StatusActionClient.DANGEROUS_PORT.

reason: Literal['REJECT', 'WARN']

When “reject”, we refused the connection; whereas if it’s “warn”, we allowed it.

port: Annotated[int]

A stream was initiated and this port is commonly used for vulnerable protocols.

class aiostem.structures.StatusClientDangerousSocks[source]

Arguments for action StatusActionClient.DANGEROUS_SOCKS.

protocol: Literal['SOCKS4', 'SOCKS5']

The protocol implied in this dangerous connection.

address: TcpAddressPort

The address and port implied in this connection.

class aiostem.structures.StatusClientSocksUnknownProtocol[source]

Arguments for action StatusActionClient.SOCKS_UNKNOWN_PROTOCOL.

This class is currently unused as the quotes are buggy. Additionally the escaping is performed as CSTRING, which we do not handle.

data: str

First few characters that were sent to Tor on the SOCKS port.

class aiostem.structures.StatusClientSocksBadHostname[source]

Arguments for action StatusActionClient.SOCKS_BAD_HOSTNAME.

hostname: str

The host name that triggered this event.

Server status

class aiostem.structures.ClockSkewSource[source]

Source of a clock skew, properly parsed.

Note

This is to be used with StatusGeneralClockSkew.

name: Literal['DIRSERV', 'NETWORKSTATUS', 'OR', 'CONSENSUS']

Name of the source.

address: TcpAddressPort | None

Optional address of the source (None with CONSENSUS).

class aiostem.structures.StatusActionServer[source]

Bases: StrEnum

Possible actions for a STATUS_SERVER event.

Note

SERVER_DESCRIPTOR_STATUS was never implemented.

EXTERNAL_ADDRESS = 'EXTERNAL_ADDRESS'

Our best idea for our externally visible IP has changed to ‘IP’.

CHECKING_REACHABILITY = 'CHECKING_REACHABILITY'

We’re going to start testing the reachability of our external OR port or directory port.

REACHABILITY_SUCCEEDED = 'REACHABILITY_SUCCEEDED'

We successfully verified the reachability of our external OR port or directory port.

GOOD_SERVER_DESCRIPTOR = 'GOOD_SERVER_DESCRIPTOR'

We successfully uploaded our server descriptor to one of the directory authorities.

NAMESERVER_STATUS = 'NAMESERVER_STATUS'

One of our name servers has changed status.

NAMESERVER_ALL_DOWN = 'NAMESERVER_ALL_DOWN'

All of our nameservers have gone down.

DNS_HIJACKED = 'DNS_HIJACKED'

Our DNS provider is providing an address when it should be saying NOTFOUND.

DNS_USELESS = 'DNS_USELESS'

Our DNS provider is giving a hijacked address instead of well-known websites.

BAD_SERVER_DESCRIPTOR = 'BAD_SERVER_DESCRIPTOR'

A directory authority rejected our descriptor.

ACCEPTED_SERVER_DESCRIPTOR = 'ACCEPTED_SERVER_DESCRIPTOR'

A single directory authority accepted our descriptor.

REACHABILITY_FAILED = 'REACHABILITY_FAILED'

We failed to connect to our external OR port or directory port successfully.

HIBERNATION_STATUS = 'HIBERNATION_STATUS'

Our bandwidth based accounting status has changed.

class aiostem.structures.ExternalAddressResolveMethod[source]

Bases: StrEnum

How the external method was resolved.

NONE = 'NONE'
CONFIGURED = 'CONFIGURED'
CONFIGURED_ORPORT = 'CONFIGURED_ORPORT'
GETHOSTNAME = 'GETHOSTNAME'
INTERFACE = 'INTERFACE'
RESOLVED = 'RESOLVED'
class aiostem.structures.StatusServerExternalAddress[source]

Arguments for action StatusActionServer.EXTERNAL_ADDRESS.

address: IPv4Address | IPv6Address

Our external IP address.

hostname: str | None

When set, we got our new IP by resolving this host name.

method: ExternalAddressResolveMethod

How we found out our external IP address.

class aiostem.structures.StatusServerCheckingReachability[source]

Arguments for action StatusActionServer.CHECKING_REACHABILITY.

or_address: TcpAddressPort | None

Checking reachability to this onion routing address that is our own.

class aiostem.structures.StatusServerReachabilitySucceeded[source]

Arguments for action StatusActionServer.REACHABILITY_SUCCEEDED.

or_address: TcpAddressPort | None

Reachability succeeded to our onion routing address.

class aiostem.structures.StatusServerReachabilityFailed[source]

Arguments for action StatusActionServer.REACHABILITY_FAILED.

or_address: TcpAddressPort | None

Reachability failed to our onion routing address.

class aiostem.structures.StatusServerNameserverStatus[source]

Arguments for action StatusActionServer.NAMESERVER_STATUS.

ns: str

This is our name server.

status: LivenessStatus

This is its status.

err: str | None

Error message when status is DOWN.

class aiostem.structures.StatusServerBadServerDescriptor[source]

Arguments for action StatusActionServer.BAD_SERVER_DESCRIPTOR.

dir_auth: TcpAddressPort

Directory that rejected our descriptor as an address and port.

reason: str

Include malformed descriptors, incorrect keys, highly skewed clocks, and so on.

class aiostem.structures.StatusServerAcceptedServerDescriptor[source]

Arguments for action StatusActionServer.ACCEPTED_SERVER_DESCRIPTOR.

dir_auth: TcpAddressPort

Directory that accepted our server descriptor as an address and port.

class aiostem.structures.StatusServerHibernationStatus[source]

Arguments for action StatusActionServer.HIBERNATION_STATUS.

status: Literal['AWAKE', 'SOFT', 'HARD']