Computing microdescriptors
Microdescriptors are a stripped-down version of server descriptors generated by the directory authorities which may additionally contain authority-generated information. Microdescriptors contain only the most relevant parts that clients care about. Microdescriptors are expected to be relatively static and only change about once per week. Microdescriptors do not contain any information that clients need to use to decide which servers to fetch information about, or which servers to fetch information from.
Microdescriptors are a straight transform from the server descriptor and the consensus method. Microdescriptors have no header or footer. A microdescriptor is identified by the SHA256 hash of its concatenated elements without a signature by the router. Microdescriptors do not contain any version information, because their version is determined by the consensus method.
Starting with consensus method 8, microdescriptors contain the following elements taken from or based on the server descriptor. Order matters here, because different directory authorities must be able to transform a given server descriptor and consensus method into the exact same microdescriptor.
Microdescriptor items
onion-key — Intro item
onion-key- Exactly once, at start.
- No extra arguments.
- Optional Object, a public key in PEM format.
Optionally, an obsolete TAP key.
(Note that while the key is optional,
the onion-key element itself is not.
It is used to denote the start of a microdescriptor.)
This key is no longer used for anything. If present, it MUST be in the same format as described for relay descriptors.
All current consensus methods generate a key in this position.
ntor-onion-key — KP_ntor, the circuit extension key
As
ntor-onion-key in router descriptors.
When generating microdescriptors for consensus method 30 or later, the trailing = sign must be absent. For consensus method 29 or earlier, the trailing = sign must be present.
(Only included when generating microdescriptors for consensus-method 16 or later.)
[Before Tor 0.4.5.1-alpha, this field was optional.]
a — Further router address(es) (IPv6)
As
a in consensus.
Additional advertised addresses for the OR.
Present currently only if the OR advertises at least one IPv6 address; currently, the first address is included and all others are omitted. Any other IPv4 or IPv6 addresses should be ignored.
Address and port are as for “or-address” as specified in section 2.1.1.
(Only included when generating microdescriptors for consensus-methods 14 to 27.)
family — Normalised declared family membership
As “family” in server descriptors.
When generating microdescriptors for consensus method 29 or later, the following canonicalization algorithm is applied to improve compression:
-
For all entries of the form $hexid=name or $hexid~name, remove the =name or ~name portion.
-
Remove all entries of the form $hexid, where hexid is not 40 hexadecimal characters long.
-
If an entry is a valid nickname, put it into lower case.
-
If an entry is a valid $hexid, put it into upper case.
-
If there are any entries, add a single $hexid entry for the relay in question, so that it is a member of its own family.
-
Sort all entries in lexical order.
-
Remove duplicate entries.
(Note that if an entry is not of the form “nickname”, “$hexid”, “$hexid=nickname” or “$hexid~nickname”, then it will be unchanged: this is what makes the algorithm forward-compatible.)
Clients use these family lists to determine family membership when building paths.
family-ids — Proved family membership
family-idsid ..- At most once.
Each id is a Family IDs. Each family ID consists of any number of otherwise valid nonspace characters.
Authorities generate a family-ids entry by deriving an ID
from each of the family-certs
listed in the relay’s router descriptor,
sorting those IDs in lexicographic order, and removing any duplicates.
Clients use these family IDs to determine family membership when building paths.
Clients SHOULD accept family IDs in unrecognized formats.
[This entry first appeared in consensus method 35. Earlier methods should omit it.]
p — Exit policy summary, IPv4
paccept|rejectPortList- At most once.
An exit-policy summary summarizing the router’s supported exit ports, to “most addresses”.
Approximate calculation
With microdescriptors, clients don’t learn exact exit policies: clients can only guess whether a relay accepts their request, try the BEGIN request, and might get end-reason-exit-policy if they guessed wrong, in which case they’ll have to try elsewhere.
The exit policy summary must be computed in reasonable time and space, bearing in mind that router descriptors might maliciously try to exhaust dirauth resources. Therefore, a dirauth SHOULD use an approximate algorithm, rather than attempting to precisely follow the defined semantics.
Considering relays which publish pathological policies to manipulate the summarisation algorithm: It is best if a relay cannot deliberately cause an over-optimistic summary (one which lists ports open when they’re mostly closed); It does not matter if a relay can maliciously cause an over-pessimistic summary.
Detailed algorithm
The currently specified algorithm (for Arti) is:
- Iterate over all exit policy items, in order.
- Disregard items whose addrspec matches no IPv4 addresses (ie, disregard IPv6 subnets).
- Disregard
rejects whose addrspec is an IPv4 subnet completely contained within a private network (see below). - For other
rejectlines, add the size of the subnet (its number of contained IP addresses) to the “rejected address count”. If the “rejected address count” exceeds the 2^25 limit, stop and list the port as closed. - For an
acceptitem which matches all IPv4 addresses, stop and list the port as open. - Otherwise, on reaching the end of the exit policy items, list the port as open.
- Return a result as if we had run this algorithm independently for each possible port number (but use a rangemap data structure for efficiency).
In consensus methods before 100 (C Tor), different algorithm(s) are used.
Public addresses
For the purpose of this computation, private networks are:
- 0.0.0.0/8 - This Network, RFC791 3.2
- 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 - Private-Use, RFC1918
- 100.64.0.0/10 - Shared Address Space, RFC6598
- 127.0.0.0/8 - Loopback, RFC1122 3.2.1.3
- 169.254.0.0/16 - Link Local, RFC3927
- 192.0.0.0/24 - IETF Protocol Assignments, RFC6890
- 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 - Documentation (TEST-NET-[123]), RFC5737
- 198.18.0.0/15 - Benchmarking, RFC2544
- 192.31.196.0/24 - AS112-v4 (reverse lookup for private addrs) RFC7535
- 192.175.48.0/24, 192 - Direct Delegation AS112 RFC5734
- 255.255.255.255/32 - “Limited Broadcast”, RFC8190, RFC919 s7
See IPv4 Special-Purpose Address Space, IANA
192.0.0.0/24 (IETF Protocol Assignments) contains a variety of sub-allocations for individual protocols. All of those allocated so far (As of 2026-06-23) would all be reasonable or desirable for an exit relay to reject.
AS112 is a mechanism for providing reverse DNS for private-use addresses. This should not be used via Tor.
There is no reason to reject the reserved multicast block (240/4): if a protocol which uses it is designed and implemented, there is no reason a Tor client ought not to be able to access it.
NOT treated as private for port summary purposes, even though they are Special-Purpose IPv4 address space, are:
- 192.52.193.0/24 - AMT Relay Discovery Address Prefix (UDP), RFC7450
- 192.88.99.0/24 - Deprecated 6to4 Relay Anycast, RFC7526
- 192.88.99.2/32 - 6a44-relay anycast, RFC6751
- 240.0.0.0/4 - Reserved (multicast), RFC1112 s4
Changes to the set of networks considered private involve a change to the consensus method.
Every network considered “private” from the point of view of the default relay exit policy SHOULD also be considered private from the point of view of this algorithm. Therefore, we should not add a new rejected “private” network to the relay exit policy without first deploying a new consensus method that considers it private.
This list of private networks may not be suitable for use by an exit relay as a basis for its exit policy or for calculating its exit policy summary. Current exit relay implementations provide a default reject list which is much shorter than the list above.
This list is definitely not suitable for use by Tor clients trying to avoid accidentally leaking local traffic to the Tor network.
p6 — Exit policy summary, IPv6
p6accept|rejectPortList- At most once.
The IPv6
An exit-policy summary
A missing “p6” line is equivalent to p6 reject 1-65535.
(Only included when generating microdescriptors for consensus-method 15 or later.)
id rsa1024 — RSA relay identity, H(KP_relayid_rsa)
id rsa1024base64-encoded-identity-digest- At most once.
The node identity digest SHA1(DER(KP_relayid_rsa)), base64
encoded, without trailing =s. This line is included to prevent
collisions between microdescriptors.
Implementations SHOULD ignore these lines: they are added to microdescriptors only to prevent collisions.
(Only included when generating microdescriptors for consensus-method 18 or later.)
id ed25519 — ed25519 relay identity, H(KP_relayid_ed)
id ed25519base64-encoded-ed25519-identity- At most once.
The node’s master Ed25519 identity key, base64 encoded,
without trailing =s.
All implementations MUST ignore this key for any microdescriptor whose corresponding entry in the consensus includes the ‘NoEdConsensus’ flag.
(Only included when generating microdescriptors for consensus-method 21 or later.)
id other-keytype — other relay identity
idkeytype ..- At most once per distinct keytype.
Implementations MUST ignore “id” lines with unrecognized key-types in place of “rsa1024” or “ed25519”
(Note that with microdescriptors, clients do not learn the RSA identity of their routers: they only learn a hash of the RSA identity key. This is all they need to confirm the actual identity key when doing a TLS handshake, and all they need to put the identity key digest in their CREATE cells.)