How mpcium Manages Node Identity and Verifies Peer Messages
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 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 (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 (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 (line 109). This function performs a multi-step validation process:
-
Load the local private key – Reads the node's private key file, decrypting it with age if the optional passphrase parameter is provided (
loadPrivateKeyat line 25). -
Validate the peer registry – Loads
peers.json, which maps every node name to itsnode_id. For each entry, the store validates that a matching<node>_identity.jsonfile exists, parses the public key, and verifies that thenode_idin the file matches the one declared inpeers.json(peer validation loop at line 51). -
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 (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 (line 52), the registry creates the store instance and injects it into session constructors. The session implementation in 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.jsonandpeers.jsonto establish a trust anchor backed by Ed25519 key pairs. - Strict peer validation: The
NewFileStoreconstructor validates that every peer'snode_idmatches its public key file before allowing communication. - Deterministic signing: All TSS and ECDH messages are signed using
SignMessageandSignEcdhMessagewith Ed25519 signatures over deterministic encodings. - Multi-scheme verification: The store verifies peer messages via
VerifyMessage, initiator events viaVerifyInitiatorMessage(supporting Ed25519 and P-256), and enforces optional multi-authorizer policies viaAuthorizeInitiatorMessage. - Encrypted channels: Symmetric keys established during ECDH are managed through
SetSymmetricKey, with transparent encryption viaEncryptMessageandDecryptMessage.
Frequently Asked Questions
How does mpcium prevent identity spoofing during peer discovery?
mpcium prevents spoofing by requiring each node to validate the 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 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →