---
updatedAt: 2026-08-19T00:58:47.000Z
agentTools:
  projectIndex: https://vault.docs.blockdaemon.com/llms.txt
---

# Key Management Lifecycle

The Institutional Vault ensures that a complete private key never exists at any point in its lifecycle. The following sections describe the data flow for key generation, encrypted storage, and threshold signing.

***

### Key Generation

Private keys are generated through a distributed key generation (DKG) protocol coordinated by the Wallet Service orchestrator. Each MPA Node independently contributes cryptographically secure randomness, and the MPC protocol produces a key share per node along with a shared public key. The complete private key is never assembled, computed, or transmitted.

```mermaid
%%{init: {'themeVariables': { 'noteBkgColor': '#9370DB', 'noteTextColor': '#ffffff', 'noteBorderColor': '#4B0082' }}}%%
sequenceDiagram
    participant Client as API Client
    participant WS as Wallet Service<br/>(Orchestrator)
    participant NATS as Broker
    participant PN0 as MPA Node 0
    participant PN1 as MPA Node 1
    participant PN2 as MPA Node 2

    Client->>WS: CreateMasterKey request
    WS->>NATS: Distribute DKG session
    NATS->>PN0: DKG round
    NATS->>PN1: DKG round
    NATS->>PN2: DKG round
    Note over PN0,PN2: Each node contributes<br/>local CSPRNG randomness
    PN0-->>PN1: MPC protocol messages
    PN1-->>PN2: MPC protocol messages
    PN2-->>PN0: MPC protocol messages
    Note over PN0,PN2: DKG completes:<br/>each node holds a key share<br/>complete key never exists
    PN0->>PN0: Encrypt share (AES-256-GCM)<br/>and persist to local DB
    PN1->>PN1: Encrypt share (AES-256-GCM)<br/>and persist to local DB
    PN2->>PN2: Encrypt share (AES-256-GCM)<br/>and persist to local DB
    PN0-->>WS: Public key + success
    WS-->>Client: MasterKey created (public key)
```

***

### Key Storage

Each policy node's key share is encrypted at rest using AES-256-GCM with a per-node Master Encryption Key (MEK) derived via HKDF. Encrypted shares are persisted to that node's isolated PostgreSQL database. Shares are protected at rest (cloud KMS / Key Vault), in transit (TLS and mTLS between nodes), and in use inside a hardware-attested Trusted Execution Environment (TEE) on AWS Nitro Enclaves or Azure Confidential Containers.

> For Nitro and Azure Confidential Container isolation, KMS attestation, hardware-bound storage, and how MPC combines with TEE versus physical HSMs, see [MPC and TEE Security Architecture](mpc-tee-security-architecture).

```mermaid
---
config:
  themeVariables:
    fontSize: 16px
    fontFamily: arial
---
flowchart TD
    subgraph node0 [MPA Node 0]
        MEK0["MEK 0"]
        HKDF0["HKDF"]
        AES0["AES-256-GCM Encrypt"]
        Share0["Key Share 0<br/>(in-memory only)"]
        Share0 --> AES0
        MEK0 --> HKDF0
        HKDF0 --> AES0
        AES0 --> Enc0["Encrypted Share 0"]
    end

    subgraph node1 [MPA Node 1]
        MEK1["MEK 1"]
        HKDF1["HKDF"]
        AES1["AES-256-GCM Encrypt"]
        Share1["Key Share 1<br/>(in-memory only)"]
        Share1 --> AES1
        MEK1 --> HKDF1
        HKDF1 --> AES1
        AES1 --> Enc1["Encrypted Share 1"]
    end

    subgraph node2 [MPA Node 2]
        MEK2["MEK 2"]
        HKDF2["HKDF"]
        AES2["AES-256-GCM Encrypt"]
        Share2["Key Share 2<br/>(in-memory only)"]
        Share2 --> AES2
        MEK2 --> HKDF2
        HKDF2 --> AES2
        AES2 --> Enc2["Encrypted Share 2"]
    end

    subgraph storage [Isolated Databases]
        DB0["MPA Node 0<br/>PostgreSQL"]
        DB1["MPA Node 1<br/>PostgreSQL"]
        DB2["MPA Node 2<br/>PostgreSQL"]
    end

    Enc0 --> DB0
    Enc1 --> DB1
    Enc2 --> DB2

    subgraph tee [TEE Protection]
        Nitro["AWS Nitro Enclave /<br/>Azure Confidential Containers"]
        KMS["KMS Remote Attestation"]
        Nitro --> KMS
    end

    MEK0 -.->|"Protected by"| Nitro
    MEK1 -.->|"Protected by"| Nitro
    MEK2 -.->|"Protected by"| Nitro
```

***

### Key Usage (Signing)

When a transaction intent is submitted, it passes through policy evaluation and approval before the Wallet Service initiates a threshold MPC signing ceremony. Each MPA Node decrypts its share in memory, validates the transaction against the approved intent, and participates in the multi-party signing protocol. The partial signatures are combined into a single standard ECDSA or EdDSA signature. The complete private key is never reconstructed during signing.

```mermaid
%%{init: {'themeVariables': { 'noteBkgColor': '#9370DB', 'noteTextColor': '#ffffff', 'noteBorderColor': '#4B0082' }}}%%
sequenceDiagram
    participant WS as Wallet Service<br/>(Orchestrator)
    participant NATS as Broker
    participant PN0 as MPA Node 0
    participant PN1 as MPA Node 1
    participant PN2 as MPA Node 2
    Note over WS: Transaction approval<br/>quorum completed

    WS->>NATS: Initiate signing ceremony
    NATS->>PN0: Sign request
    NATS->>PN1: Sign request
    NATS->>PN2: Sign request

    PN0->>PN0: Decrypt share with MEK<br/>from local DB
    PN1->>PN1: Decrypt share with MEK<br/>from local DB
    PN2->>PN2: Decrypt share with MEK<br/>from local DB

    Note over PN0,PN2: Pre-sign validation:<br/>outputs, fees, spec,<br/>code authorizations<br/>must match intent

    PN0-->>PN1: MPC signing protocol
    PN1-->>PN2: MPC signing protocol
    PN2-->>PN0: MPC signing protocol

    Note over PN0,PN2: Threshold signing completes:<br/>single ECDSA/EdDSA signature<br/>key never reconstructed

    PN0-->>WS: Combined signature
```