iroh SecretKey, PublicKey, and EndpointId: Understanding the Relationship
In iroh, EndpointId is a type alias for PublicKey, which is cryptographically derived from the SecretKey via SecretKey::public(), creating a direct identity chain where the endpoint's public identifier is exactly its Ed25519 public key.
The iroh networking library uses Ed25519 cryptography to establish peer identity. In the n0-computer/iroh repository, the relationship between SecretKey, PublicKey, and EndpointId forms the foundation of endpoint authentication and network identification.
How iroh SecretKey, PublicKey, and EndpointId Form a Cryptographic Chain
Iroh implements a strict hierarchical relationship between these three types. The secret key holds the private Ed25519 signing material, the public key represents the verifiable public counterpart, and the endpoint ID serves as the network-visible identifier.
SecretKey as the Root of Identity
The SecretKey struct in iroh-base/src/key.rs holds the private Ed25519 signing key. This key authenticates the endpoint and cryptographically signs all messages. When you need to prove identity or establish secure connections, the secret key provides the cryptographic material.
PublicKey and the EndpointId Type Alias
The PublicKey is derived directly from the SecretKey using the SecretKey::public() method. According to the source code in iroh-base/src/key.rs lines 98-101, this method returns the public counterpart of the signing key.
Critically, EndpointId is defined as a type alias for PublicKey in iroh-base/src/key.rs lines 58-70. This means:
- Every endpoint's identifier is exactly the public key of its secret key
- No conversion or transformation occurs between
PublicKeyandEndpointId - Two endpoints sharing the same
EndpointIdmust possess the same underlying secret key pair
Implementation in the iroh Crates
The relationship is implemented across the core iroh-base and iroh crates, with specific file locations handling different aspects of the identity chain.
iroh-base: Key Generation and Aliasing
In iroh-base/src/key.rs, the library defines the fundamental types:
SecretKey::public()(lines 98-101): Derives the public key from the secretEndpointIdalias (lines 58-70): DeclaresEndpointIdas equivalent toPublicKey
When you call SecretKey::generate(), the library creates a new random Ed25519 keypair. The public portion is immediately accessible without additional computation.
iroh: Endpoint Construction and Identity Binding
In iroh/src/endpoint.rs, the Endpoint builder integrates these cryptographic primitives:
- Lines 24-31: The builder stores the
SecretKeyinEndpointInnerduring construction - Lines 66-72: The
Endpoint::id()method returns the stored public key/endpoint ID - Lines 61-64: The
Endpoint::secret_key()accessor retrieves the original secret key - Lines 24-27: When no secret key is provided, the builder calls
SecretKey::generate()automatically
Practical Usage Examples
Generating Keys and Deriving EndpointId
When working with iroh directly, you can observe the relationship between these types:
use iroh_base::{SecretKey, EndpointId};
fn main() {
// 1. Create a new secret key (randomly)
let secret = SecretKey::generate();
// 2. Derive its public key
let public = secret.public();
// 3. The endpoint identifier is exactly this public key
let endpoint_id: EndpointId = public; // type alias, no conversion needed
// 4. All three are linked
assert_eq!(endpoint_id, secret.public());
println!("SecretKey: {:?}", secret);
println!("EndpointId: {}", endpoint_id); // prints hex representation
}
Endpoint Builder Integration
When constructing an endpoint, the builder handles the secret key generation and ID extraction internally:
use iroh::{Endpoint, endpoint::presets};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Builder generates a random SecretKey internally
let ep = Endpoint::builder(presets::N0).bind().await?;
// The generated secret key can be inspected
let secret = ep.secret_key();
let id = ep.id(); // <-- this is the public key of `secret`
assert_eq!(id, secret.public());
println!("Endpoint ID (public key): {}", id);
Ok(())
}
The builder extracts the endpoint ID via secret_key.public() and stores it in EndpointInner, making the identity available through the Endpoint::id() method.
Summary
- SecretKey holds the private Ed25519 signing material in
iroh-base/src/key.rs - PublicKey is derived via
SecretKey::public()and represents the cryptographic public identity - EndpointId is a type alias for
PublicKey(lines 58-70 iniroh-base/src/key.rs), meaning the endpoint's network ID is exactly its public key - The Endpoint builder in
iroh/src/endpoint.rs(lines 24-31) automatically generates or accepts a secret key and exposes the ID viaEndpoint::id() - Because
EndpointIdis the public key, any two endpoints with the same ID must share the same underlying secret key pair
Frequently Asked Questions
What is the exact relationship between EndpointId and PublicKey in iroh?
EndpointId is a type alias for PublicKey defined in iroh-base/src/key.rs lines 58-70. This means they are the same type with different names—EndpointId serves as the network identifier while PublicKey describes the cryptographic function. No conversion is necessary between them.
How do I generate a SecretKey and retrieve the corresponding EndpointId?
Call SecretKey::generate() to create a random Ed25519 keypair, then use SecretKey::public() to retrieve the public key, which is also the EndpointId. In iroh/src/endpoint.rs lines 24-27, the endpoint builder performs this automatically when binding to a network interface.
Can two different endpoints have the same EndpointId?
No. Because EndpointId is exactly the PublicKey derived from the SecretKey, and Ed25519 public keys are uniquely determined by their private keys, two endpoints can only share an EndpointId if they possess the same SecretKey. This cryptographic relationship ensures unique endpoint identification across the network.
Where is the EndpointId stored in the iroh source code?
The EndpointId is stored in EndpointInner during endpoint construction, as seen in iroh/src/endpoint.rs lines 24-31. The Endpoint::id() method (lines 66-72) forwards this value, while the underlying SecretKey remains accessible via Endpoint::secret_key() (lines 61-64).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →