Skip to content

Instantly share code, notes, and snippets.

@mikedotexe
Created December 17, 2025 20:45
Show Gist options
  • Select an option

  • Save mikedotexe/e2b9c3aa2c9b077baef741e535b40a4a to your computer and use it in GitHub Desktop.

Select an option

Save mikedotexe/e2b9c3aa2c9b077baef741e535b40a4a to your computer and use it in GitHub Desktop.
Claude talking Outlayer and MPC and TEE

TEE Key Management for Multi-Chain Automation

A guide to understanding how Trusted Execution Environments (TEEs) enable automated, secure key management across multiple blockchains.


The Problem: Key Management is Hard

Self-Custody

You hold your own keys. Sounds great until:

  • You lose them - Seed phrases get lost, hardware fails, people die without passing on access
  • You get phished - Social engineering, fake sites, malicious contract approvals
  • You have to be present - Every transaction needs your signature. Can't automate. Can't sleep.
  • Multi-chain is a nightmare - Different wallets, different formats, different seed phrases for each chain

The numbers don't lie: billions in crypto lost to user error. Most people shouldn't be responsible for their own keys.

Custodians

Let someone else hold the keys. Simple, but:

  • Single point of failure - They get hacked, you lose everything
  • Trust required - You're trusting humans with access
  • "Not your keys, not your crypto" - They could rug, freeze, or lose your funds
  • Regulatory risk - They're subject to legal pressure you can't control

The Automation Problem

Even if you solve custody, there's a deeper issue: you can't automate what requires your signature.

Want to:

  • Rebalance your portfolio weekly?
  • Take profit when price hits X?
  • Arbitrage across chains?
  • Execute complex DeFi strategies?

With self-custody, you have to be at your computer, signing transactions. No automation possible.

With custodians, you're trusting them to execute correctly. They could front-run you, fail to execute, or simply make mistakes.


The Middle Ground: TEE Key Management

What is a TEE?

A Trusted Execution Environment is a hardware-enforced secure enclave inside a CPU. Think of it as a black box that:

  1. Runs code in isolation - Even the server operator can't peek inside
  2. Measures its own code - Produces a cryptographic hash of what's running
  3. Proves itself to the world - The hardware manufacturer signs attestation quotes

The most relevant TEE today is Intel TDX (Trust Domain Extensions).

How It Works

┌─────────────────────────────────────────────────────────┐
│                     Server                              │
│                                                         │
│   ┌─────────────────────────────────────────────────┐   │
│   │              TEE Enclave (TDX)                  │   │
│   │                                                 │   │
│   │   Code runs here                                │   │
│   │   Keys live here                                │   │
│   │   Operator CANNOT see inside                    │   │
│   │                                                 │   │
│   │   CPU measures code → RTMR3 (hash)              │   │
│   │   Intel signs attestation quote                 │   │
│   │                                                 │   │
│   └─────────────────────────────────────────────────┘   │
│                                                         │
│   Operator can start/stop enclave                       │
│   Operator CANNOT extract keys or modify code           │
│                                                         │
└─────────────────────────────────────────────────────────┘

The Trust Model

You're not trusting a company. You're trusting:

  1. The code - It's open source, auditable, you can verify what it does
  2. The hardware - Intel/AMD attestation proves the code is actually running in a real enclave

If you trust the code (it's audited) and the hardware confirms that exact code is running, you can trust the output without trusting the operator.

Why This Enables Automation

The TEE can hold keys and sign transactions 24/7:

  • Deterministic execution - Code does exactly what it says
  • No human in the loop - Operator can't interfere with signing
  • Always available - Signs while you sleep
  • Programmable - Define rules, TEE executes them

It's like having a robot that holds your keys and only does what the audited code tells it to do.


The Persistence Problem

TEE Memory is Volatile

Here's the catch: when a TEE enclave shuts down, everything in memory is gone.

┌─────────────────────────┐
│ TEE (running)           │
│                         │
│ master_secret: 0xABC... │
│ derived keys in memory  │
│                         │
└─────────────────────────┘
            │
            │ restart / crash / hardware swap
            ▼
┌─────────────────────────┐
│ TEE (fresh boot)        │
│                         │
│ master_secret: ???      │
│ keys: ???               │
│                         │
└─────────────────────────┘

If the master secret is lost, all derived keys are lost. User funds are locked forever.

What Happens on Restart?

The TEE needs a way to recover its master secret. There are three approaches:

Approach How It Works Tradeoff
Sealed storage Encrypt to disk with hardware-bound key Breaks if hardware changes
MPC derivation Derive from NEAR MPC Network Requires MPC availability
User backup User provides master secret User's responsibility

MPC Key Derivation (CKD)

The NEAR MPC Network

NEAR has a Multi-Party Computation network where multiple nodes hold threshold shares of a master secret. No single node knows the complete secret.

This network can:

  1. Sign transactions (Chain Signatures) - Produce signatures for any chain
  2. Derive secrets (CKD) - Produce deterministic secrets for any derivation path

How CKD Works

When the TEE needs its master secret:

┌─────────────────────┐                    ┌─────────────────────┐
│ TEE                 │                    │ MPC Network         │
│                     │                    │                     │
│ 1. Generate fresh   │                    │                     │
│    keypair (a, A)   │                    │                     │
│    a = private      │                    │                     │
│    A = public       │                    │                     │
│                     │                    │                     │
│         "Derive secret for path         │                     │
│          'alice.near:keystore'          │                     │
│          Here's my public key A"        │                     │
│ ───────────────────────────────────────>│                     │
│                     │                    │                     │
│                     │                    │ 2. Each MPC node    │
│                     │                    │    computes partial │
│                     │                    │    value using its  │
│                     │                    │    secret share     │
│                     │                    │                     │
│                     │                    │ 3. Combine partials │
│                     │                    │    Encrypt to A     │
│                     │                    │                     │
│                     │    Enc(A, secret)  │                     │
│ <───────────────────────────────────────│                     │
│                     │                    │                     │
│ 4. Decrypt with a   │                    │                     │
│    → master_secret  │                    │                     │
│                     │                    │                     │
└─────────────────────┘                    └─────────────────────┘

Why This Is Secure

  • MPC nodes never see the final secret - They only see encrypted partials
  • Network transport sees only ciphertext - Encrypted to TEE's public key
  • Only the TEE can decrypt - It holds the private key a
  • Deterministic - Same derivation path always produces same secret

Why This Solves Persistence

Day 1: TEE boots
       TEE asks MPC: derive("alice.near:keystore")
       MPC returns: encrypted(0xABC123...)
       TEE decrypts: 0xABC123...
       TEE uses 0xABC123... as master secret
       TEE derives all keys from master secret

Day 2: TEE restarts (crash, update, hardware change)
       TEE asks MPC: derive("alice.near:keystore")  ← same request
       MPC returns: encrypted(0xABC123...)          ← same answer
       TEE decrypts: 0xABC123...                    ← same secret
       TEE derives same keys

Funds still accessible.

The MPC network is the persistence layer. The TEE is stateless. Same question, same answer, forever.


The Complete Flow

Step 1: TEE Boots and Gets Its Secret

TEE                              MPC Network
 │                                    │
 │  CKD("alice.near:keystore")        │
 │ ──────────────────────────────────>│
 │                                    │
 │         encrypted(master_secret)   │
 │ <──────────────────────────────────│
 │                                    │
 │  Decrypt → master_secret           │
 │  Derive child keys                 │
 │                                    │

Step 2: TEE Proves Itself to DAO

TEE                              DAO Contract
 │                                    │
 │  register_worker_key(pubkey, quote)│
 │ ──────────────────────────────────>│
 │                                    │
 │        ┌───────────────────────────┤
 │        │ Verify Intel attestation  │
 │        │ Check RTMR3 is approved   │
 │        │ Store pubkey → RTMR3 map  │
 │        └───────────────────────────┤
 │                                    │
 │              ✓ Registered          │
 │ <──────────────────────────────────│
 │                                    │

On-chain: One transaction. Happens once per TEE instance.

Step 3: User Requests Cross-Chain Address

User        Keystore (TEE)           chain-keys Contract
 │               │                          │
 │  "ETH addr"   │                          │
 │ ─────────────>│                          │
 │               │                          │
 │    ┌──────────┤                          │
 │    │ Derive   │                          │
 │    │ secp256k1│                          │
 │    │ keypair  │                          │
 │    └──────────┤                          │
 │               │                          │
 │               │  register_tee_key(...)   │
 │               │ ────────────────────────>│
 │               │                          │
 │               │        ┌─────────────────┤
 │               │        │ Verify RTMR3    │
 │               │        │ (cross-contract)│
 │               │        │ Derive address  │
 │               │        │ Store binding   │
 │               │        └─────────────────┤
 │               │                          │
 │               │  ✓ 0x7E5F4552...         │
 │               │ <────────────────────────│
 │               │                          │
 │  0x7E5F4552...│                          │
 │ <─────────────│                          │

On-chain: One transaction per (user, chain) pair. Stores the address binding with TEE attestation proof.

Step 4: User Signs Transactions

User        Keystore (TEE)           Ethereum
 │               │                      │
 │  "Sign this"  │                      │
 │ ─────────────>│                      │
 │               │                      │
 │    ┌──────────┤                      │
 │    │ Sign TX  │                      │
 │    │ inside   │                      │
 │    │ enclave  │                      │
 │    └──────────┤                      │
 │               │                      │
 │  Signed TX    │                      │
 │ <─────────────│                      │
 │               │                      │
 │  Broadcast ─────────────────────────>│
 │               │                      │

On-chain (NEAR): None! Signing happens off-chain in TEE.

On-chain (target): The signed transaction lands on Ethereum/Bitcoin/etc.

Step 5: TEE Restarts

TEE (new instance)               MPC Network
 │                                    │
 │  CKD("alice.near:keystore")        │
 │ ──────────────────────────────────>│
 │                                    │
 │         encrypted(master_secret)   │  ← Same as before
 │ <──────────────────────────────────│
 │                                    │
 │  Decrypt → same master_secret      │
 │  Derive same child keys            │
 │                                    │
 │  Ready to sign again               │
 │                                    │

On-chain: None. The keys are re-derived, not recovered from storage.


Where chain-keys Fits

The On-Chain Address Book

chain-keys is a NEAR contract that stores cross-chain address bindings:

alice.near
├── secp256k1:abc... → 0x7E5F4552... (Ethereum)
│                      └── tee_attestation:
│                          tee_type: "tdx"
│                          rtmr3: "abc123..."
│                          verified_at: block 12345678
│
├── secp256k1:def... → bc1p0xlx... (Bitcoin Taproot)
│                      └── tee_attestation: ...
│
└── ed25519:ghi... → BGCCDDHf... (Solana)
                     └── tee_attestation: ...

Why This Matters for Automation

Automated systems need to know: "What addresses am I operating?"

Automation Logic
      │
      │ "I need to swap on Uniswap"
      │ "What's my Ethereum address?"
      │
      ▼
┌─────────────────┐
│ chain-keys      │  ← Query on-chain
│                 │
│ alice.near:     │
│   ETH: 0x7E5... │
│   BTC: bc1p...  │
│   SOL: BGCC...  │
└─────────────────┘
      │
      │ "Use 0x7E5F... for this swap"
      │
      ▼
   Keystore signs

What chain-keys Provides

Capability Without chain-keys With chain-keys
Address lookup Ask keystore Query on-chain
Attestation proof Trust keystore Verify on-chain
Persistence Keystore availability Always available
Composability N/A Other contracts can query

The Registry-Only Model

chain-keys stores bindings but doesn't add NEAR access keys:

// register_tee_key: Registry only, no NEAR access key
// - Stores the binding with attestation proof
// - Does NOT add key to NEAR account
// - Perfect for cross-chain TEE keys

This is the typical case for TEE keystores where keys sign for Ethereum/Bitcoin but not NEAR.


Deployment Models

MPC-Backed (Default)

┌─────────────────┐         ┌─────────────────┐
│ TEE Keystore    │ <────── │ NEAR MPC Network│
│                 │   CKD   │                 │
│ Derives keys    │         │ Threshold secret│
│ on boot         │         │ (persistence)   │
└─────────────────┘         └─────────────────┘
  • Persistence: MPC network
  • Recovery: Automatic on restart
  • Trust: MPC network + TEE hardware

Self-Hosted

┌─────────────────┐         ┌─────────────────┐
│ TEE Keystore    │ <────── │ User's backup   │
│                 │  config │                 │
│ Derives keys    │         │ MASTER_SECRET   │
│ on boot         │         │ (user stores)   │
└─────────────────┘         └─────────────────┘
  • Persistence: User's backup
  • Recovery: User provides secret
  • Trust: TEE hardware only

Managed Phala

┌─────────────────┐
│ Phala Network   │
│                 │
│ ┌─────────────┐ │
│ │ Worker 1    │ │  Shared: Multiple users per worker
│ └─────────────┘ │         Key derivation isolates them
│                 │
│ ┌─────────────┐ │
│ │ Worker 2    │ │  Dedicated: One user per worker
│ └─────────────┘ │            Maximum isolation
│                 │
└─────────────────┘
  • Persistence: Phala infrastructure + MPC or sealed storage
  • Recovery: Depends on configuration
  • Trust: Phala + TEE hardware

For NEAR Developers

Chain Signatures vs TEE Signing

NEAR offers two paths for cross-chain operations:

Chain Signatures (MPC) TEE Signing
Who signs MPC network TEE enclave
Key storage Threshold shares TEE memory (derived from MPC)
Latency Higher (coordination) Lower (single signer)
Trust MPC network Code + hardware
Automation Via contract calls Via keystore API

When to Use Each

Use Chain Signatures when:

  • You need maximum decentralization
  • Signing frequency is low
  • You're building contract-to-contract flows

Use TEE Signing when:

  • You need high-frequency signing
  • You want programmable key management
  • You're building automated strategies

Integration Points

Your App
    │
    ├── Query chain-keys: "What's alice's ETH address?"
    │   └── On-chain, always available
    │
    ├── Request signing: POST to keystore API
    │   └── Off-chain, TEE signs
    │
    └── Verify attestation: Query chain-keys
        └── On-chain, includes RTMR3 proof

Summary

Component Role
TEE Holds keys, signs transactions, runs audited code
MPC Network Provides deterministic secret derivation (persistence)
DAO Contract Verifies TEE attestation, stores approved code measurements
chain-keys On-chain address book with attestation proof

The result: Automated multi-chain key management with verifiable security.

  • Keys never leave TEE memory
  • Persistence via MPC derivation, not storage
  • On-chain proof of TEE provenance
  • Queryable cross-chain identity

One NEAR account. All chains. Programmable. Verifiable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment