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 PublicKey and EndpointId
  • Two endpoints sharing the same EndpointId must 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 secret
  • EndpointId alias (lines 58-70): Declares EndpointId as equivalent to PublicKey

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 SecretKey in EndpointInner during 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 in iroh-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 via Endpoint::id()
  • Because EndpointId is 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →