# How mpcium Manages Node Identity and Verifies Peer Messages

> Discover how mpcium manages node identity with Ed25519 keys and verifies peer messages using signature verification for TSS, ECDH, and initiator communications.

- Repository: [Fystack Labs/mpcium](https://github.com/fystack/mpcium)
- Tags: internals
- Published: 2026-03-02

---

**mpcium uses a file-backed identity store (`identity.Store`) that persists each node's Ed25519 key material in JSON files, validates peer identities against a [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json) registry, and enforces cryptographic signature verification for all TSS, ECDH, and initiator messages.**

mpcium implements a robust identity management system where each node maintains a cryptographically bound identity stored in the filesystem. The architecture ensures that nodes verify each other's authenticity through Ed25519 signatures and optional multi-authorizer policies before participating in multi-party computation (MPC) sessions.

## Identity Store Architecture

### Node Identity Structure

Each node in the network is defined by a JSON file named `<node>_identity.json` that contains a human-readable name, a UUID (`node_id`), the node's hex-encoded public key, and a creation timestamp. This structure is defined in the `NodeIdentity` struct in **[`pkg/identity/identity.go`](https://github.com/fystack/mpcium/blob/main/pkg/identity/identity.go)** (line 30). The private key is stored separately and can be optionally encrypted using the age file encryption format.

### The Store Interface

The `Store` interface abstracts all identity-related operations behind a unified API. According to the source in **[`pkg/identity/identity.go`](https://github.com/fystack/mpcium/blob/main/pkg/identity/identity.go)** (line 37), this interface includes methods for public-key lookup, message signing, TSS and ECDH verification, symmetric-key handling, and optional authorizer checks. This abstraction allows the MPC runtime to remain agnostic of the underlying storage mechanism while enforcing strict cryptographic boundaries.

## Bootstrapping and Peer Validation

The identity system is initialized through the `NewFileStore` constructor in **[`pkg/identity/identity.go`](https://github.com/fystack/mpcium/blob/main/pkg/identity/identity.go)** (line 109). This function performs a multi-step validation process:

1. **Load the local private key** – Reads the node's private key file, decrypting it with age if the optional passphrase parameter is provided (`loadPrivateKey` at line 25).

2. **Validate the peer registry** – Loads [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json), which maps every node name to its `node_id`. For each entry, the store validates that a matching `<node>_identity.json` file exists, parses the public key, and verifies that the `node_id` in the file matches the one declared in [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json) (peer validation loop at line 51).

3. **Cache public keys** – After verification, all peer public keys are cached in memory to eliminate filesystem I/O during message processing.

## Cryptographic Message Verification

### Signing Messages

When a node transmits TSS or ECDH messages, it invokes `SignMessage` or `SignEcdhMessage` from the store. Both functions marshal the message into a deterministic byte slice and sign it with the node's Ed25519 private key. These methods are implemented in **[`pkg/identity/identity.go`](https://github.com/fystack/mpcium/blob/main/pkg/identity/identity.go)** (`SignMessage` at line 63, `SignEcdhMessage` at line 31).

### Verifying Peer Messages

Upon receipt, messages undergo strict verification through the `VerifyMessage` method (line 75). The process extracts the sender's `node_id` from the TSS `PartyID`, retrieves the cached public key via `GetPublicKey`, re-marshals the message content, validates the Ed25519 signature using `ed25519.Verify`, and only then passes the message to the MPC state machine. ECDH messages follow an identical flow via `VerifySignature` (line 42).

### Initiator and Authorizer Verification

Initiator messages—such as key-generation requests—require additional validation through `VerifyInitiatorMessage` (line 67). The implementation supports both Ed25519 and P-256 (ECDSA) signature schemes, dispatching to `verifyEd25519` (line 55) or `verifyP256` (line 71) based on the configured initiator key type.

If the optional authorization feature is enabled, `AuthorizeInitiatorMessage` (line 79) enforces multi-signature policies. This function verifies that every required authorizer's signature is present and valid against cached authorizer public keys using `verifyAuthorizerSignature` (line 20), ensuring no single compromised initiator can unilaterally trigger sensitive operations.

## Session Key Management

During the ECDH key-exchange phase, nodes establish confidential channels by deriving symmetric keys stored via `SetSymmetricKey`. Subsequent traffic is encrypted using `EncryptMessage` and decrypted via `DecryptMessage`, ensuring that all MPC traffic remains confidential even if the underlying transport is compromised.

## MPC Runtime Integration

The identity store is composed into the MPC runtime at two critical points. In **[`pkg/mpc/registry.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/registry.go)** (line 52), the registry creates the store instance and injects it into session constructors. The session implementation in **[`pkg/mpc/session.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/session.go)** then utilizes the store for signing outgoing TSS messages (line 12) and verifying incoming ones (line 123), creating a seamless security boundary around the threshold signing protocol.

## Summary

- **File-backed storage**: Each node uses `<node>_identity.json` and [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json) to establish a trust anchor backed by Ed25519 key pairs.
- **Strict peer validation**: The `NewFileStore` constructor validates that every peer's `node_id` matches its public key file before allowing communication.
- **Deterministic signing**: All TSS and ECDH messages are signed using `SignMessage` and `SignEcdhMessage` with Ed25519 signatures over deterministic encodings.
- **Multi-scheme verification**: The store verifies peer messages via `VerifyMessage`, initiator events via `VerifyInitiatorMessage` (supporting Ed25519 and P-256), and enforces optional multi-authorizer policies via `AuthorizeInitiatorMessage`.
- **Encrypted channels**: Symmetric keys established during ECDH are managed through `SetSymmetricKey`, with transparent encryption via `EncryptMessage` and `DecryptMessage`.

## Frequently Asked Questions

### How does mpcium prevent identity spoofing during peer discovery?

mpcium prevents spoofing by requiring each node to validate the [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json) registry against individual `<node>_identity.json` files during the `NewFileStore` initialization. The constructor explicitly checks that the `node_id` declared in [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json) matches the `node_id` inside the corresponding identity file, and that the public key parses correctly. This binds the UUID to a specific cryptographic key before any message verification occurs.

### What signature schemes does mpcium support for identity verification?

mpcium uses **Ed25519** as its primary signature algorithm for peer-to-peer TSS and ECDH messages. For initiator messages, the system supports both **Ed25519** and **P-256 (ECDSA)** curves, allowing integration with existing PKI infrastructures. The `verifyEd25519` and `verifyP256` functions in [`pkg/identity/identity.go`](https://github.com/fystack/mpcium/blob/main/pkg/identity/identity.go) handle the specific curve validation logic.

### Can mpcium enforce multi-signature authorization for sensitive operations?

Yes. When the authorizer feature is enabled, the `AuthorizeInitiatorMessage` method requires that initiator messages carry signatures from a configured set of authorizers. The store verifies each signature against cached authorizer public keys using `verifyAuthorizerSignature`, ensuring that policy-defined thresholds (e.g., 2-of-3 administrators) are met before the MPC session begins.

### How are private keys protected at rest?

Private keys are stored separately from the public identity files and can be encrypted using the **age** file encryption format. When initializing the store with `NewFileStore`, operators can specify an `age.pass` file containing the passphrase. If encryption is enabled, the `loadPrivateKey` function decrypts the private key before loading it into memory, protecting against offline filesystem compromises.