pub struct HiddenServiceDescriptorV3 {
pub version: u32,
pub lifetime: u32,
pub signing_cert: Option<String>,
pub revision_counter: u64,
pub superencrypted: Option<String>,
pub signature: String,
/* private fields */
}Expand description
Version 3 hidden service descriptor.
A v3 hidden service descriptor uses modern Ed25519/X25519 cryptography
and provides stronger security than v2 descriptors. The .onion address
is 56 characters long (vs 16 for v2).
§Structure
The descriptor contains:
version: Always 3 for this typelifetime: How long the descriptor is valid (in minutes)signing_cert: Ed25519 certificate for the descriptor signing keyrevision_counter: Monotonically increasing counter to prevent replaysuperencrypted: Encrypted outer layer (contains inner layer)signature: Ed25519 signature over the descriptor
§Encryption Layers
V3 descriptors have two encryption layers:
- Superencrypted (outer): Decrypted with blinded key + subcredential
- Encrypted (inner): May require client authorization cookie
The decryption process requires:
- The service’s blinded public key (derived from identity key + time)
- The subcredential (derived from identity key)
- Optionally, the client’s authorization cookie
§Address Format
V3 .onion addresses are 56 characters and encode:
- 32 bytes: Ed25519 public key
- 2 bytes: Checksum
- 1 byte: Version (0x03)
Use address_from_identity_key and
identity_key_from_address to convert.
§Example
use stem_rs::descriptor::hidden::HiddenServiceDescriptorV3;
use stem_rs::descriptor::Descriptor;
let content = std::fs::read_to_string("v3_descriptor.txt")?;
let desc = HiddenServiceDescriptorV3::parse(&content)?;
println!("Version: {}", desc.version);
println!("Lifetime: {} minutes", desc.lifetime);
println!("Revision: {}", desc.revision_counter);
// Convert identity key to .onion address
let key = [0u8; 32]; // Your 32-byte Ed25519 public key
let address = HiddenServiceDescriptorV3::address_from_identity_key(&key);
println!("Address: {}", address);§Security
- The
revision_counterprevents replay attacks - The
signatureauthenticates the descriptor - Introduction points are encrypted and require decryption
- Client authorization adds an additional encryption layer
Fields§
§version: u32Hidden service descriptor version (always 3 for this type).
lifetime: u32Descriptor validity period in minutes (typically 180).
signing_cert: Option<String>Ed25519 certificate for the descriptor signing key (PEM format).
revision_counter: u64Monotonically increasing counter to prevent replay attacks.
superencrypted: Option<String>Encrypted outer layer containing client auth and inner layer.
signature: StringEd25519 signature over the descriptor content.
Implementations§
Source§impl HiddenServiceDescriptorV3
impl HiddenServiceDescriptorV3
Sourcepub fn address_from_identity_key(key: &[u8]) -> String
pub fn address_from_identity_key(key: &[u8]) -> String
Converts an Ed25519 identity key to a v3 .onion address.
The address is computed as:
- Compute checksum: SHA3-256(“.onion checksum” || pubkey || version)[0:2]
- Concatenate: pubkey || checksum || version
- Base32-encode and append “.onion”
§Arguments
key- 32-byte Ed25519 public key
§Returns
A 62-character string ending in “.onion” (56 chars + “.onion”).
§Example
use stem_rs::descriptor::hidden::HiddenServiceDescriptorV3;
let key = [0u8; 32];
let address = HiddenServiceDescriptorV3::address_from_identity_key(&key);
assert!(address.ends_with(".onion"));
assert_eq!(address.len(), 62); // 56 + ".onion"Sourcepub fn identity_key_from_address(onion_address: &str) -> Result<Vec<u8>, Error>
pub fn identity_key_from_address(onion_address: &str) -> Result<Vec<u8>, Error>
Extracts the Ed25519 identity key from a v3 .onion address.
Validates the address format, checksum, and version byte.
§Arguments
onion_address- A v3.onionaddress (with or without “.onion” suffix)
§Returns
The 32-byte Ed25519 public key on success.
§Errors
Returns Error::Parse if:
- The address is not valid base32
- The decoded length is not 35 bytes
- The version byte is not 3
- The checksum does not match
§Example
use stem_rs::descriptor::hidden::HiddenServiceDescriptorV3;
let key = [0u8; 32];
let address = HiddenServiceDescriptorV3::address_from_identity_key(&key);
let recovered = HiddenServiceDescriptorV3::identity_key_from_address(&address).unwrap();
assert_eq!(recovered, key.to_vec());§Security
The checksum prevents typos in addresses from connecting to the wrong service. Always validate addresses before use.
Trait Implementations§
Source§impl Clone for HiddenServiceDescriptorV3
impl Clone for HiddenServiceDescriptorV3
Source§fn clone(&self) -> HiddenServiceDescriptorV3
fn clone(&self) -> HiddenServiceDescriptorV3
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more