# Difference Between iroh EndpointId, PublicKey, and SecretKey Explained

> Understand the difference between iroh EndpointId, PublicKey, and SecretKey. Learn how these keys form iroh's identity chain for secure network communication.

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

---

**In iroh, `EndpointId` is simply a type alias for `PublicKey`, which is cryptographically derived from the `SecretKey` using Ed25519 key pairs, forming a direct identity chain where the secret key signs messages and the public key identifies the endpoint on the network.**

The n0-computer/iroh distributed systems framework implements a strict cryptographic hierarchy for peer identity. Understanding the difference between these three types is essential for secure peer-to-peer networking, as they collectively handle authentication, signing, and network addressing within the iroh protocol stack.

## The Cryptographic Hierarchy

The relationship between **SecretKey**, **PublicKey**, and **EndpointId** follows a deterministic one-way derivation implemented in the `iroh-base` crate:

1. **SecretKey** – Holds the private Ed25519 signing key used to authenticate messages and establish identity.
2. **PublicKey** – The public counterpart derived deterministically from the secret key via elliptic curve cryptography.
3. **EndpointId** – A type alias for `PublicKey` that semantically represents the network-facing identifier of an endpoint.

This architecture ensures that every endpoint's network identity is exactly the public key of its underlying secret key pair, with no additional abstraction layer or hashing involved.

### SecretKey: The Private Signing Authority

The **SecretKey** contains the sensitive cryptographic material that proves ownership of an endpoint. In [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs), lines 98-101, the `SecretKey::public()` method performs the Ed25519 derivation to generate the corresponding public key. When an endpoint is constructed without an explicit key, the builder automatically generates a random secret key using `SecretKey::generate()` as seen in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), lines 24-27.

### PublicKey: The Verifiable Identity

The **PublicKey** allows other peers to verify signatures and confirm message authenticity without accessing private material. This type represents the raw cryptographic identity that can be shared freely across the network. According to the source code in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs), lines 98-101, the public key is computed deterministically from the secret key using standard Ed25519 derivation.

### EndpointId: The Network Alias

**EndpointId** is defined in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs), lines 58-70, as a direct type alias for `PublicKey`. This design choice provides semantic clarity—distinguishing between a generic public key and one specifically used as an endpoint identifier—while maintaining zero-cost interoperability. Because it is merely an alias, any `PublicKey` can be used as an `EndpointId` without conversion or runtime overhead.

## Implementation in the iroh Source Code

The connection between these types is enforced at the API level in both the cryptographic primitives and the endpoint builder.

### Key Derivation in iroh-base

The [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs) file defines the core relationship. Lines 58-70 establish the `EndpointId` alias, while lines 98-101 implement the `SecretKey::public()` method that performs the actual cryptographic derivation. This ensures that the three concepts remain tightly coupled at the type system level.

### Endpoint Builder Integration

When constructing an `Endpoint` in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), the builder stores the secret key in `EndpointInner` (lines 24-31). The `Endpoint::id()` method (lines 66-72) simply returns the pre-computed public key, while `Endpoint::secret_key()` (lines 61-64) provides access to the private material. This implementation guarantees that `ep.id()` is always exactly `ep.secret_key().public()`.

## Practical Code Examples

### Generating Keys and Accessing the EndpointId

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

fn main() {
    // Generate a new random Ed25519 secret key
    let secret = SecretKey::generate();
    
    // Derive the public key (zero-cost operation)
    let public = secret.public();
    
    // EndpointId is exactly the public key
    let endpoint_id: EndpointId = public;
    
    // All three references point to the same identity
    assert_eq!(endpoint_id, secret.public());
    println!("Endpoint ID: {}", endpoint_id);
}

```

### Using the Endpoint Builder

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

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Builder generates SecretKey automatically if not provided
    let ep = Endpoint::builder(presets::N0).bind().await?;
    
    // Access the generated secret and its public identifier
    let secret = ep.secret_key();
    let id = ep.id(); // Returns the PublicKey as EndpointId
    
    // Verify the relationship
    assert_eq!(id, secret.public());
    println!("Endpoint ID: {}", id);
    Ok(())
}

```

## Summary

- **SecretKey** contains the private Ed25519 signing material and must remain confidential to the node.
- **PublicKey** is cryptographically derived from `SecretKey` via the `public()` method defined in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs).
- **EndpointId** is a type alias for `PublicKey`, meaning the endpoint's network identity is exactly its public key with no additional encoding.
- The implementation in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) enforces that `Endpoint::id()` always returns `secret_key.public()`, ensuring cryptographic consistency.

## Frequently Asked Questions

### Can two endpoints have the same EndpointId with different SecretKeys?

No. Because `EndpointId` is exactly the `PublicKey`, and the public key is deterministically derived from the `SecretKey` via Ed25519, two endpoints sharing the same `EndpointId` must possess identical underlying secret key pairs. This cryptographic binding ensures that endpoint identity is unforgeable without access to the private key material.

### Why does iroh use a type alias for EndpointId instead of a wrapper struct?

The type alias defined in [`iroh-base/src/key.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/key.rs), lines 58-70, provides semantic clarity for API consumers while maintaining zero-cost interoperability with `PublicKey` operations. This design allows functions to accept `EndpointId` specifically when an endpoint identifier is semantically required, while avoiding conversion overhead or wrapper indirection that would occur with a distinct struct type.

### How do I persist a SecretKey between application restarts?

The `SecretKey` type implements serialization traits that allow you to export the private key bytes. Store these bytes securely using OS-level secret management (such as keychains or encrypted configuration files), then deserialize and provide the key to `Endpoint::builder()` when reconstructing the endpoint. Never log the secret key or transmit it over the network, as possession of the secret key grants complete control over the endpoint's identity.

### Is EndpointId used for encryption or just identification?

The `EndpointId` (being the public key) is primarily used for **identification** and **signature verification**. While Ed25519 keys can be used in X25519 key exchange protocols for encryption, in iroh the `EndpointId` serves as the stable network address and authentication credential. It identifies which peer sent a message and verifies that message's cryptographic signature, but does not directly encrypt payload data.