Documentation
¶
Index ¶
- func BlindPublicKey(pubkey [32]byte, periodNumber int64, periodLength int64) ([32]byte, error)
- func BuildRendLinkSpecs(identity [20]byte, address string, orPort uint16, ed25519ID [32]byte) ([]byte, error)
- func ConnectOnionService(address string, port uint16, consensus *directory.Consensus, ...) (io.ReadWriteCloser, error)
- func CurrentTimePeriod() int64
- func DecodeOnion(address string) ([32]byte, error)
- func DecryptDescriptorLayer(encrypted []byte, secretData, subcredential []byte, revisionCounter uint64, ...) ([]byte, error)
- func FetchDescriptor(client *http.Client, hsdirAddr string, blindedKey [32]byte) (string, error)
- func FetchDescriptorViaCircuit(circ *circuit.Circuit, blindedKey [32]byte) (string, error)
- func GenerateRendezvousCookie() ([20]byte, error)
- func GetSRVForClient(consensus *directory.Consensus) ([]byte, error)
- func HsNtorClientCompleteHandshake(state *HsNtorClientState, serverPK [32]byte, auth [32]byte) ([]byte, error)
- func HsNtorExpandKeys(ntorKeySeed []byte) (df, db [32]byte, kf, kb [32]byte)
- func IsOnionAddress(target string) bool
- func NewRendezvousDigests(df, db [32]byte) (hashDf, hashDb sha3Hash)
- func PickRandomHSDir(candidates []*directory.Relay) (*directory.Relay, error)
- func SelectHSDirs(consensus *directory.Consensus, blindedKey [32]byte, ...) ([]*directory.Relay, error)
- func Subcredential(pubkey [32]byte, blindedKey [32]byte) [32]byte
- func TimePeriod(t time.Time, periodLength int64) int64
- func TimePeriodFromConsensus(consensus *directory.Consensus) int64
- type BuiltCircuit
- type CircuitBuilder
- type ConnectResult
- type DescriptorOuter
- type HsNtorClientState
- type IntroPoint
- type ParsedLinkSpecs
- type RendezvousKeys
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BlindPublicKey ¶
BlindPublicKey derives the blinded public key A' = h * A for the given time period. The nonce N = "key-blind" | INT_8(period_number) | INT_8(period_length).
func BuildRendLinkSpecs ¶
func BuildRendLinkSpecs(identity [20]byte, address string, orPort uint16, ed25519ID [32]byte) ([]byte, error)
BuildRendLinkSpecs encodes link specifiers for a rendezvous point in the format expected by INTRODUCE1 plaintext: NSPEC | (LSTYPE | LSLEN | LSPEC)...
func ConnectOnionService ¶
func ConnectOnionService( address string, port uint16, consensus *directory.Consensus, httpClient *http.Client, builder CircuitBuilder, logger *slog.Logger, ) (io.ReadWriteCloser, error)
ConnectOnionService performs the full v3 onion service connection protocol: resolve descriptor, establish rendezvous, introduce, and complete handshake. Returns an io.ReadWriteCloser for the connected stream.
func CurrentTimePeriod ¶
func CurrentTimePeriod() int64
CurrentTimePeriod computes the time period from the current time. Prefer TimePeriodFromConsensus when a consensus is available.
func DecodeOnion ¶
DecodeOnion decodes a v3 .onion address and returns the 32-byte Ed25519 public key. It validates the checksum, version byte, and rejects keys with torsion components.
func DecryptDescriptorLayer ¶
func DecryptDescriptorLayer(encrypted []byte, secretData, subcredential []byte, revisionCounter uint64, stringConstant string) ([]byte, error)
DecryptDescriptorLayer decrypts one layer of a v3 HS descriptor. The encrypted blob format is: SALT(16) | ENCRYPTED(variable) | MAC(32)
Parameters:
- encrypted: the raw encrypted blob
- secretData: SECRET_DATA (blinded_public_key for outer, blinded_public_key|descriptor_cookie for inner)
- subcredential: the 32-byte subcredential
- revisionCounter: the descriptor's revision counter
- stringConstant: "hsdir-superencrypted-data" for outer, "hsdir-encrypted-data" for inner
func FetchDescriptor ¶
FetchDescriptor fetches a v3 hidden service descriptor from the given HSDir relay. The request is made to the relay's DirPort using the blinded public key to construct the URL: /tor/hs/3/<base64_blinded_key>
Per rend-spec-v3, this request should be made anonymously over a Tor circuit. The client parameter allows routing through Tor.
func FetchDescriptorViaCircuit ¶
FetchDescriptorViaCircuit fetches a v3 hidden service descriptor using BEGIN_DIR over an existing circuit (for HSDirs without a public DirPort). The circuit's last hop must be the HSDir relay.
func GenerateRendezvousCookie ¶
GenerateRendezvousCookie generates a random 20-byte rendezvous cookie.
func GetSRVForClient ¶
GetSRVForClient returns the appropriate SRV for a client to use, per rend-spec-v3 §2.2.4.1. Between a new TP and a new SRV, use current SRV. Between a new SRV and a new TP, use previous SRV.
func HsNtorClientCompleteHandshake ¶
func HsNtorClientCompleteHandshake(state *HsNtorClientState, serverPK [32]byte, auth [32]byte) ([]byte, error)
HsNtorClientCompleteHandshake completes the client side of the hs-ntor handshake upon receiving the RENDEZVOUS2 message containing SERVER_PK (Y) and AUTH. Returns the key seed for key expansion.
func HsNtorExpandKeys ¶
HsNtorExpandKeys derives the relay encryption keys from the NTOR_KEY_SEED. K = KDF(NTOR_KEY_SEED | m_hsexpand, SHA3_256_LEN*2 + S_KEY_LEN*2) Returns Df(32), Db(32), Kf(32), Kb(32).
func IsOnionAddress ¶
IsOnionAddress returns true if the target address is a .onion address.
func NewRendezvousDigests ¶
func NewRendezvousDigests(df, db [32]byte) (hashDf, hashDb sha3Hash)
NewRendezvousDigests creates SHA3-256 running digests initialized with the given seeds. These are used for relay cell authentication on the onion service circuit (as opposed to SHA-1 for regular circuit hops).
func PickRandomHSDir ¶
PickRandomHSDir picks a random HSDir from the candidate list.
func SelectHSDirs ¶
func SelectHSDirs(consensus *directory.Consensus, blindedKey [32]byte, periodNum, periodLength int64, srv []byte) ([]*directory.Relay, error)
SelectHSDirs selects the HSDirs to fetch a descriptor from for the given blinded public key and time period, per rend-spec-v3 §2.2.3.
func Subcredential ¶
Subcredential computes the subcredential for a given time period. N_hs_subcred = SHA3-256("subcredential" | N_hs_cred | blinded_public_key) N_hs_cred = SHA3-256("credential" | public_identity_key)
func TimePeriod ¶
TimePeriod computes the current time period number. tp = (minutes_since_epoch - rotation_time_offset) / time_period_length
func TimePeriodFromConsensus ¶
TimePeriodFromConsensus computes the time period number using the consensus valid-after time (not the system clock), per rend-spec-v3.
Types ¶
type BuiltCircuit ¶
type BuiltCircuit struct {
Circuit *circuit.Circuit
LinkCloser io.Closer // Closes the underlying TLS link
LastHop *descriptor.RelayInfo // Info about the last relay in the circuit
}
BuiltCircuit holds a circuit and the metadata about the last hop, needed for the onion service protocol.
type CircuitBuilder ¶
type CircuitBuilder interface {
// BuildCircuit builds a 3-hop circuit. If target is non-nil, it is used
// as the last hop instead of a randomly selected exit.
BuildCircuit(target *descriptor.RelayInfo) (*BuiltCircuit, error)
}
CircuitBuilder abstracts the ability to build a 3-hop Tor circuit.
type ConnectResult ¶
type ConnectResult struct {
IntroPoints []IntroPoint
BlindedKey [32]byte
Subcred [32]byte
Descriptor *DescriptorOuter
}
ConnectResult holds the information needed to establish a stream to an onion service after the introduction/rendezvous protocol completes.
func ResolveOnionService ¶
func ResolveOnionService(address string, consensus *directory.Consensus, httpClient *http.Client, builder ...CircuitBuilder) (*ConnectResult, error)
ResolveOnionService resolves a .onion address to a set of introduction points by fetching and decrypting the service descriptor. This is the first step before the introduction/rendezvous protocol.
Parameters:
- address: the v3 .onion address (with or without .onion suffix)
- consensus: the current consensus
- httpClient: HTTP client for fetching the descriptor (can be nil if builder is provided)
- builder: optional circuit builder for BEGIN_DIR fetch (used when DirPort=0)
type DescriptorOuter ¶
type DescriptorOuter struct {
LifetimeSeconds int
SigningKeyCert []byte // The signing key certificate
RevisionCounter uint64
Superencrypted []byte // The superencrypted blob
Signature []byte
}
ParseDescriptorOuterLayer parses the outer layer of a v3 HS descriptor, returning the fields needed for decryption.
func ParseDescriptorOuter ¶
func ParseDescriptorOuter(text string) (*DescriptorOuter, error)
ParseDescriptorOuter parses the outer plaintext layer of an HS descriptor.
type HsNtorClientState ¶
type HsNtorClientState struct {
X [32]byte // Client ephemeral public key
B [32]byte // Service encryption key (KP_hss_ntor / enc-key ntor)
AuthKey []byte // Introduction point auth key
Subcred [32]byte // Subcredential
// contains filtered or unexported fields
}
HsNtorClientState holds the client's ephemeral state during an hs-ntor handshake.
func BuildINTRODUCE1 ¶
func BuildINTRODUCE1(authKey []byte, encKey [32]byte, subcredential [32]byte, rendCookie [20]byte, rendNodeOnionKey [32]byte, rendLinkSpecs []byte) ([]byte, *HsNtorClientState, error)
BuildINTRODUCE1 builds the INTRODUCE1 relay cell payload. Parameters:
- authKey: the introduction point's auth key (from descriptor)
- encKey: the service's enc-key ntor (curve25519, from descriptor)
- subcredential: the service's subcredential
- rendCookie: 20-byte rendezvous cookie
- rendNodeOnionKey: the rendezvous point's ntor onion key
- rendLinkSpecs: the rendezvous point's link specifiers (encoded for EXTEND2)
Returns the full INTRODUCE1 payload and the hs-ntor client state for completing the handshake when RENDEZVOUS2 arrives.
func HsNtorClientHandshake ¶
func HsNtorClientHandshake(B [32]byte, authKey []byte, subcredential [32]byte) (*HsNtorClientState, [32]byte, [32]byte, error)
HsNtorClientHandshake initiates the client side of an hs-ntor handshake. It generates the ephemeral keypair, derives the encryption and MAC keys for the INTRODUCE1 encrypted section, and returns the client state.
B is the service's enc-key (curve25519 public key from the descriptor). authKey is the introduction point's auth key. subcredential is the service's subcredential for the current period.
type IntroPoint ¶
type IntroPoint struct {
// LinkSpecifiers is the raw link specifiers block for use in EXTEND2.
LinkSpecifiers []byte
// OnionKey is the ntor onion key of the introduction point relay (curve25519).
OnionKey [32]byte
// AuthKeyCert is the raw auth-key certificate.
AuthKeyCert []byte
// AuthKey is the 32-byte Ed25519 auth key extracted from the certificate.
AuthKey [32]byte
// EncKey is the curve25519 encryption key for the hs-ntor handshake (KP_hss_ntor).
EncKey [32]byte
// EncKeyCert is the raw enc-key-cert certificate.
EncKeyCert []byte
}
IntroPoint represents a parsed introduction point from a v3 HS descriptor.
func DecryptAndParseDescriptor ¶
func DecryptAndParseDescriptor(outer *DescriptorOuter, blindedKey [32]byte, subcredential [32]byte) ([]IntroPoint, error)
DecryptAndParseDescriptor decrypts both layers of a v3 HS descriptor and returns the list of introduction points.
type ParsedLinkSpecs ¶
type ParsedLinkSpecs struct {
Address string // IPv4 or IPv6 address
ORPort uint16
Identity [20]byte // RSA identity (SHA-1 fingerprint)
Ed25519ID [32]byte
HasEd25519 bool
}
ParsedLinkSpecs holds the extracted fields from link specifiers.
func ParseLinkSpecifiers ¶
func ParseLinkSpecifiers(data []byte) (*ParsedLinkSpecs, error)
ParseLinkSpecifiers parses the NSPEC-prefixed link specifier block (as stored in IntroPoint.LinkSpecifiers) into structured fields.
type RendezvousKeys ¶
type RendezvousKeys struct {
Df [32]byte // Forward digest seed (SHA3-256)
Db [32]byte // Backward digest seed (SHA3-256)
Kf [32]byte // Forward AES-256-CTR key
Kb [32]byte // Backward AES-256-CTR key
}
RendezvousKeys holds the derived keys for an onion service circuit.
func CompleteRendezvous ¶
func CompleteRendezvous(state *HsNtorClientState, rendezvous2Body []byte) (*RendezvousKeys, error)
CompleteRendezvous processes the RENDEZVOUS2 message from the rendezvous point, completing the hs-ntor handshake and deriving circuit keys. The rendezvous2Body contains: SERVER_PK(32) | AUTH(32).