# How EndpointId, PublicKey, and SecretKey Work in iroh: Identity and Authentication Explained

> Understand iroh's EndpointId PublicKey and SecretKey. Learn how the secret key authenticates endpoints and the public key identifies them in this identity and authentication guide.

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

---

**In iroh, `EndpointId` is a type alias for `PublicKey`, which is cryptographically derived from `SecretKey`, forming a chain where the secret key authenticates the endpoint and the public key identifies it.**

In the iroh networking crate, identity and authentication rely on a tightly coupled trio of types: `SecretKey`, `PublicKey`, and `EndpointId`. Understanding the relationship between these three concepts is essential for building secure peer-to-peer applications with iroh. This article breaks down how these types connect in the source code and how they function in practice.

## The Cryptographic Relationship Between SecretKey, PublicKey, and EndpointId

### SecretKey as the Private Foundation

The **SecretKey** holds the private Ed25519 signing key used to authenticate the endpoint. According to the iroh source code, this type is defined in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs) and provides the cryptographic root of trust for any endpoint.

### PublicKey as the Verifiable Identity

Derived directly from the `SecretKey` via the `public()` method, the **PublicKey** represents the public portion of the key pair. In [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs) at lines 98-101, the `SecretKey::public()` method returns a `PublicKey` that can be used to verify signatures generated by the secret key.

### EndpointId as the Network Identifier

**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) at lines 58-70. This means every endpoint's identifier is exactly the public key of its secret key, ensuring that network identity is cryptographically bound to the authentication key.

## How the Connection Is Implemented in iroh

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

The `Endpoint::id()` method simply forwards this stored value, as implemented in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) at lines 66-72. Similarly, `Endpoint::secret_key()` provides access to the secret key at lines 61-64.

The flow follows this exact chain:

1. `SecretKey` generates or accepts the private key material.
2. `PublicKey` derives from `SecretKey::public()`.
3. `EndpointId` aliases `PublicKey`, making them identical types for network identification.

## Practical Usage Examples

### Manual Key Generation and Relationship Verification

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

fn main() {
    // Generate a new secret key
    let secret = SecretKey::generate();
    
    // Derive the public key
    let public = secret.public();
    
    // EndpointId is exactly this public key
    let endpoint_id: EndpointId = public;
    
    // Verify the relationship
    assert_eq!(endpoint_id, secret.public());
    println!("Endpoint ID: {}", endpoint_id);
}

```

### Using the Endpoint Builder with Auto-Generated Keys

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

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

```

## Summary

- **`SecretKey`** holds the private Ed25519 signing key and serves as the root of authentication.
- **`PublicKey`** derives from `SecretKey` via `SecretKey::public()` and acts as the verifiable identity.
- **`EndpointId`** is a type alias for `PublicKey`, meaning the endpoint's network identifier is exactly its public key.
- The `Endpoint` builder in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) manages this relationship automatically, storing the secret key and exposing the ID via `endpoint.id()`.

## Frequently Asked Questions

### Is EndpointId just a PublicKey?

Yes. In the iroh source code, `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) at lines 58-70. They are the same type, meaning any function accepting an `EndpointId` can accept a `PublicKey` directly without conversion.

### Can I use a custom SecretKey when creating an Endpoint?

Yes. The `Endpoint` builder accepts a user-provided `SecretKey`. If none is provided, the builder automatically generates one using `SecretKey::generate()` during the `bind()` process, as seen in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) at lines 24-31.

### How does the Builder handle SecretKey generation?

When building an endpoint without an explicit secret key, the implementation in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) calls `SecretKey::generate()` to create a random Ed25519 key pair. It then stores this in `EndpointInner` and derives the `EndpointId` from `secret_key.public()`.

### Where are these types defined in the source code?

The `SecretKey`, `PublicKey`, and `EndpointId` types are defined in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs). The `Endpoint` integration that connects these types to the networking stack is implemented in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), specifically in the builder pattern and the `id()` accessor methods.