Skip to main content
Mole managing signing keys

signing-key

Authenticate sleep/wake commands with Ed25519 signatures. Generate signing keypairs that let authorized operators control mesh hibernation while preventing unauthorized parties from putting your mesh to sleep.

What this protects: Without signing keys, anyone who can reach an agent's HTTP API or connect to the mesh can trigger sleep/wake commands. With signing keys, only operators with the private key can issue valid commands.

Quick setup:

# Generate a keypair
muti-metroo signing-key generate

# Add public key to ALL agents (they verify signatures)
# Add private key ONLY to operator nodes (they sign commands)

Subcommands

generate

Generate a new Ed25519 signing keypair:

muti-metroo signing-key generate

Output:

=== Signing Keypair Generated ===

Public Key (add to ALL agent configs):
a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd

Private Key (add ONLY to operator configs - KEEP SECRET!):
e5f6a7b8c9d012345678901234567890123456789012345678901234567890efe5f6a7b8c9d012345678901234567890123456789012345678901234567890ef

Configuration snippets:

For ALL agents (verify signatures):
management:
signing_public_key: "a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd"

For OPERATOR nodes only (sign commands):
management:
signing_public_key: "a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd"
signing_private_key: "e5f6a7b8c9d012345678901234567890123456789012345678901234567890efe5f6a7b8c9d012345678901234567890123456789012345678901234567890ef"

public

Derive public key from a private key:

muti-metroo signing-key public

The command reads the private key from stdin (input is hidden for security).

Example:

echo "e5f6a7b8c9d0..." | muti-metroo signing-key public

Output:

Signing Public Key: a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd

Usage Guide

Initial Setup

  1. Generate keypair on a secure machine:

    muti-metroo signing-key generate
  2. Save the private key securely (password manager, encrypted file)

  3. Distribute public key to all agents via config

  4. Add private key only to operator nodes that need to issue sleep/wake commands

Configuration

All agents (verify signatures - cannot issue commands):

management:
signing_public_key: "a1b2c3d4..."

Operator nodes (can sign and issue commands):

management:
signing_public_key: "a1b2c3d4..."
signing_private_key: "e5f6a7b8..."

Security Model

RoleHas Public KeyHas Private KeyCan Issue Commands
Remote AgentYesNoNo
Operator NodeYesYesYes
Agent without keysNoNoAccepts all commands
Backward Compatibility

Agents without a signing_public_key configured will accept all sleep/wake commands, signed or unsigned. For full protection, deploy the public key to ALL agents in your mesh.

Key Differences from Management Keys

FeatureManagement Keys (X25519)Signing Keys (Ed25519)
PurposeEncrypt topology dataSign sleep/wake commands
AlgorithmX25519 (encryption)Ed25519 (signatures)
Public key size32 bytes (64 hex chars)32 bytes (64 hex chars)
Private key size32 bytes (64 hex chars)64 bytes (128 hex chars)
Config keypublic_key / private_keysigning_public_key / signing_private_key

How Signing Works

When an operator triggers sleep or wake:

  1. The command includes a timestamp (nanosecond precision)
  2. The operator's agent signs the command with the private key
  3. The signed command floods to all connected agents
  4. Each agent verifies the signature using the public key
  5. Commands with invalid signatures are rejected

Replay Protection

Commands include a Unix timestamp. Agents reject commands with timestamps more than 5 minutes from the current time, preventing replay attacks.

Troubleshooting

Command Rejected

If sleep/wake commands are being rejected:

  • Verify all agents have the same signing_public_key
  • Verify the operator node has the matching signing_private_key
  • Check agent clocks are synchronized (within 5 minutes)
  • Review agent logs for signature verification errors

Mixed Deployment

If some agents accept commands and others don't:

  • Agents without signing_public_key accept all commands
  • Deploy public key to all agents for consistent behavior