How the mpcium Authorizer-Based Authorization System Works: Configuration, Verification, and CLI Workflow

The mpcium authorizer-based authorization system mandates cryptographic signatures from designated authorizers on every initiator-type message, verifying them against cached public keys using Ed25519 or P-256 algorithms before processing key generation, signing, or resharing requests.

The mpcium framework implements a robust authorization system that adds an independent security layer to threshold MPC operations. This authorizer-based model requires external approval for sensitive actions through cryptographic signatures stored in cachedAuthorizerKeys and validated via AuthorizeInitiatorMessage. According to the fystack/mpcium source code, the implementation spans three core areas: configuration management in pkg/identity/identity.go, identity generation via CLI utilities, and deterministic message verification flows.

Configuring Authorizers in mpcium

The authorization behavior is controlled by the AuthorizationConfig struct defined in pkg/identity/identity.go (lines 81-85). This configuration specifies whether the system is active, which authorizer IDs are mandatory, and the public key material for each verifier.

Authorization Configuration Structure

A typical YAML configuration lives under the top-level authorization key:

authorization:
  enabled: true                     # globally enables authorizer checks

  required_authorizers:
    - auth1                         # IDs that must sign every message

    - auth2
  authorizer_public_keys:
    auth1:
      public_key: "ab12cd..."        # hex-encoded key

      algorithm:  "ed25519"
    auth2:
      public_key: "04fe..."          # hex-encoded P-256 key

      algorithm:  "p256"

The authorization.enabled boolean acts as the global gate; when false, AuthorizeInitiatorMessage skips all checks (lines 79-84). The required_authorizers slice enforces that specific entities must sign every initiator message, while authorizer_public_keys maps IDs to their cryptographic material.

Loading and Caching Public Keys

When the store initializes via NewFileStore, the loadAuthorizationConfig function (lines 48-82) parses the configuration block. It validates each hex-encoded public key and converts them to Go crypto primitives—either ed25519.PublicKey or *ecdsa.PublicKey—storing the results in cachedAuthorizerKeys (lines 59-78). This cache eliminates repeated parsing during hot-path message verification.

Generating Authorizer Identities

New authorizers are created using the mpcium-cli generate-authorizer command implemented in cmd/mpcium-cli/generate-authorizer.go.

CLI Key Generation Workflow

The command validates the authorizer name and algorithm selection (Ed25519 or P-256) at lines 33-68. It then generates the key pair using encryption.GenerateEd25519Keys or encryption.GenerateP256Keys (lines 107-115), ensuring cryptographically secure randomness for the private material.

Output Files and Encryption

The utility produces two artifacts:

  1. *.authorizer.identity.json – Contains the authorizer ID, algorithm, and hex-encoded public key for distribution to node operators.
  2. *.authorizer.key.age – The private key encrypted with age (when using the --encrypt flag).

This separation allows operators to commit public identity files to version control while keeping private keys encrypted at rest (lines 140-199). The JSON entry is then copied into the node's authorizer_public_keys configuration map.

Verifying Initiator Messages

When a node receives an initiator message—such as GenerateKeyMessage, SignTxMessage, or ResharingMessage—the store executes a multi-stage verification pipeline defined in pkg/identity/identity.go.

The Dual-Verification Pipeline

The entry point AuthorizeInitiatorMessage (lines 79-118) performs two distinct checks:

  1. Initiator signature verificationVerifyInitiatorMessage (lines 67-77) validates the message originator using their configured algorithm.
  2. Authorizer gating – Only proceeds if authConfig.Enabled is true.

Required Authorizer Enforcement

If required_authorizers is non-empty, the function iterates through the list and ensures each ID appears in the message's AuthorizerSignatures slice (lines 85-98). Missing signatures return an immediate error identifying the deficient authorizer.

Deterministic Payload Construction

Before signature verification, the system builds a canonical signing payload using types.ComposeAuthorizerRaw in pkg/types/initiator_msg.go (lines 29-46). This function creates a deterministic JSON blob containing:

  • The initiator's ID
  • The initiator's raw payload
  • The initiator's signature

Authorizers sign this composed raw data rather than the message directly, ensuring consistent verification across distributed nodes.

Algorithm-Specific Signature Verification

The verifyAuthorizerSignature helper (lines 20-44) looks up the cached public key for each authorizer and dispatches to the appropriate verification routine:

  • Ed25519: Uses ed25519.Verify with the 32-byte public key.
  • P-256: Uses encryption.VerifyP256Signature with the uncompressed or compressed curve point.

Errors are wrapped with the authorizer ID to simplify debugging failed verifications.

Implementing Authorizer Signing

Authorizers must produce signatures over the deterministic payload. A Go implementation follows this pattern:

func signAsAuthorizer(
    authorizerPrivKey []byte, // hex-decoded private key
    authorizerAlg  types.EventInitiatorKeyType,
    msg            types.InitiatorMessage,
) (types.AuthorizerSignature, error) {

    // Build the canonical authorizer payload
    raw, err := types.ComposeAuthorizerRaw(msg)
    if err != nil {
        return types.AuthorizerSignature{}, err
    }

    // Sign with the correct algorithm
    var sig []byte
    switch authorizerAlg {
    case types.EventInitiatorKeyTypeEd25519:
        sig = ed25519.Sign(authorizerPrivKey, raw)
    case types.EventInitiatorKeyTypeP256:
        sig, err = encryption.SignWithP256(authorizerPrivKey, raw)
        if err != nil {
            return types.AuthorizerSignature{}, err
        }
    default:
        return types.AuthorizerSignature{}, fmt.Errorf("unsupported algorithm %s", authorizerAlg)
    }

    return types.AuthorizerSignature{
        AuthorizerID: "auth1", // the configured ID string
        Signature:   sig,
    }, nil
}

The resulting AuthorizerSignature struct is appended to the message's AuthorizerSignatures field before transmission to mpcium nodes.

Summary

  • The mpcium authorizer-based authorization system supports Ed25519 and P-256 cryptographic algorithms for signature verification.
  • Configuration is defined in the AuthorizationConfig struct within pkg/identity/identity.go (lines 81-85), enabling mandatory and optional authorizer lists through required_authorizers.
  • The CLI tool mpcium-cli generate-authorizer creates identity files with optional age encryption for secure private key storage.
  • Message verification follows a strict sequence: initiator signature validation, enabled-flag gating, required-authorizer presence checks, and deterministic payload verification via ComposeAuthorizerRaw.
  • Authorizers cryptographically attest to a canonical payload generated by types.ComposeAuthorizerRaw (lines 29-46), ensuring consistent replay across the distributed system.

Frequently Asked Questions

What cryptographic algorithms does mpcium support for authorizer signatures?

mpcium supports Ed25519 and P-256 (secp256r1) algorithms. The system validates these during configuration loading in loadAuthorizationConfig and uses algorithm-specific verification paths in verifyAuthorizerSignature (lines 20-44) to dispatch to either ed25519.Verify or encryption.VerifyP256Signature.

How do I add a new authorizer to an existing mpcium deployment?

Generate a new identity using mpcium-cli generate-authorizer with the --name and --algorithm flags, then copy the public key from the resulting *.authorizer.identity.json file into the authorizer_public_keys map within the node's authorization configuration. The loadAuthorizationConfig function (lines 48-82) automatically caches the new key at startup.

What happens if a required authorizer signature is missing?

The AuthorizeInitiatorMessage function returns an error indicating which required authorizer ID is absent from the message's AuthorizerSignatures slice. This check occurs at lines 85-98 in pkg/identity/identity.go, halting processing until all mandatory signatures are present.

Can authorizer private keys be stored encrypted?

Yes. The CLI's --encrypt flag triggers age encryption for the private key output file (.authorizer.key.age), while the public identity file remains unencrypted for configuration distribution. This implementation in cmd/mpcium-cli/generate-authorizer.go (lines 140-199) allows secure storage of signing material without exposing plaintext private keys.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →