# Understanding the Endpoint, SecretKey, and EndpointId Relationship in iroh

> Uncover the crucial relationship between iroh Endpoint, SecretKey, and EndpointId. Learn how PublicKey derives from SecretKey to create immutable network identities.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: deep-dive
- Published: 2026-06-22

---

**In iroh, an EndpointId is a type alias for PublicKey, which is cryptographically derived from a SecretKey using Ed25519; when you build an Endpoint, the builder extracts the public key from the secret key to establish the endpoint's immutable network identity.**

The relationship between **Endpoint**, **SecretKey**, and **EndpointId** forms the cryptographic foundation of identity and authentication in the iroh peer-to-peer networking stack. In the `n0-computer/iroh` repository, these three types are tightly coupled through primitives defined in the `iroh-base` crate, creating a deterministic chain from private signing material to public network identifier. Understanding this connection is essential for correctly configuring endpoints and managing peer identities in production applications.

## The Cryptographic Identity Chain

iroh implements a standard Ed25519 public-key cryptography model where identity flows from private to public material.

### SecretKey as the Root of Trust

The **SecretKey** holds the private Ed25519 signing key that authenticates your endpoint and signs all outgoing messages. According to the source code in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs), the `SecretKey` struct wraps the private key material and provides the `public()` method to derive its corresponding public counterpart.

When you generate a new secret key using `SecretKey::generate()`, the library creates secure random bytes suitable for Ed25519 operations. This secret must remain private to your application, as it proves ownership of the endpoint identity.

### EndpointId as PublicKey

**EndpointId** is defined as a type alias for **PublicKey** in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs) (lines 58-70). This means every endpoint's identifier is exactly the public key of its secret key, with no additional hashing or transformation applied.

The `SecretKey::public()` method (lines 98-101) performs the Ed25519 public key derivation:

```rust
use iroh_base::{SecretKey, EndpointId};

fn main() {
    // Generate a new secret key (randomly)
    let secret = SecretKey::generate();
    
    // Derive the public key
    let public = secret.public();
    
    // EndpointId is a type alias for PublicKey
    let endpoint_id: EndpointId = public;
    
    // All three are cryptographically linked
    assert_eq!(endpoint_id, secret.public());
    println!("EndpointId (PublicKey): {}", endpoint_id);
}

```

Because `EndpointId` is just the public key, any two endpoints sharing the same `EndpointId` must possess the same underlying `SecretKey` pair.

## How Endpoint Construction Establishes Identity

When building an `Endpoint`, the builder either accepts a user-provided `SecretKey` or generates one automatically via `SecretKey::generate()`. The builder then extracts the endpoint's ID via `secret_key.public()` and stores it in `EndpointInner` (as implemented in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), lines 24-31).

The `Endpoint::id()` method (lines 66-72) simply returns this pre-computed value:

```rust
use iroh::{Endpoint, endpoint::presets};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Builder generates a random SecretKey internally if none provided
    let ep = Endpoint::builder(presets::N0).bind().await?;
    
    // Access the generated secret key
    let secret = ep.secret_key();
    
    // id() returns the public key of the secret key
    let id = ep.id();
    assert_eq!(id, secret.public());
    
    println!("Endpoint ID: {}", id);
    Ok(())
}

```

You can also inspect the secret key after binding using `Endpoint::secret_key()` (lines 61-64 in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs)), which is useful for persistence and recovery scenarios.

## Practical Identity Management

Because the **Endpoint SecretKey EndpointId relationship** is deterministic and immutable, you must carefully manage key lifecycle:

- **Persistence**: Store the `SecretKey` securely if you need to maintain a stable `EndpointId` across restarts
- **Rotation**: Changing the `SecretKey` necessarily changes the `EndpointId`, breaking existing peer connections
- **Verification**: Peers use your `EndpointId` (public key) to verify signatures created by your `SecretKey`

## Summary

- **EndpointId is PublicKey**: Defined as a type alias in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs) (lines 58-70), making the endpoint identifier exactly the Ed25519 public key.
- **SecretKey drives identity**: The `SecretKey::public()` method (lines 98-101) derives the public key that becomes your endpoint's ID.
- **Builder automates linking**: The `Endpoint` builder in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 24-31) extracts the public key during construction and caches it for `Endpoint::id()` calls.
- **Cryptographic proof**: All messages signed by the `SecretKey` can be verified by anyone knowing the `EndpointId`, enabling trustless peer authentication.

## Frequently Asked Questions

### Is EndpointId just a PublicKey?

Yes. In the iroh source code, `EndpointId` is a type alias for `PublicKey` defined in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs). They are the exact same type, meaning your endpoint's network identifier is literally its Ed25519 public key bytes.

### What happens if I don't provide a SecretKey to the Endpoint builder?

If you call `Endpoint::builder()` without setting a secret key, the builder automatically generates a random `SecretKey` using `SecretKey::generate()` during the `bind()` phase (as seen in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), lines 24-27). This creates a new, ephemeral identity for that session.

### Can I reuse the same SecretKey across multiple Endpoint instances?

Yes, you can create multiple `Endpoint` instances using the same `SecretKey`, and they will all report the same `EndpointId`. However, running multiple endpoints with identical identities on the same network can cause routing conflicts and connection instability.

### How is the SecretKey used after the Endpoint is created?

The `SecretKey` remains inside the `EndpointInner` structure and is used to cryptographically sign all protocol messages, handshake attempts, and routing information. Peers verify these signatures using your `EndpointId` (public key) to confirm message authenticity without requiring prior shared secrets.