ERC-8231 — Post-Quantum Key Registry

Summary: ERC-8231 defines a standard registry for post-quantum cryptographic keys on EVM chains. It supports CRYSTALS-Dilithium-5 (FIPS 204) for signatures and CRYSTALS-Kyber-1024 (FIPS 203) for key encapsulation. Contracts can require PQ signatures on privileged actions to protect against quantum adversaries who might break ECDSA.

Why Post-Quantum

ECDSA (the signature scheme used for Ethereum transactions) is vulnerable to Shor’s algorithm on a sufficiently large quantum computer. Timeline estimates vary (5–20 years), but long-lived smart contracts — DAOs, protocol treasuries, 20-year bonds — may outlive ECDSA’s security.

ERC-8231 addresses this by standardizing how contracts can require Dilithium-5 signatures alongside (or instead of) ECDSA signatures.

Covenant Surface

ConstructDescription
pq_keyPost-quantum public key type (2,592 bytes for Dilithium-5)
@pq_signed(key)Guard: require a valid Dilithium-5 signature from key
pq_keygen()Intrinsic: generate a PQ keypair (off-chain)
pq_register(pk)Register a PQ public key in the ERC-8231 registry
pq_verify(sig, msg, pk)Verify a Dilithium-5 signature

Supported Algorithms

CRYSTALS-Dilithium-5 (FIPS 204) — Signatures

ParameterValue
NIST level5 (256-bit quantum security)
Public key size2,592 bytes
Signature size4,627 bytes
Private key size4,864 bytes
Signing time (off-chain)~1ms
Verification time (EVM precompile)~3ms / 80,000 gas

Dilithium-5 is the largest/most secure of the Dilithium family. For less critical applications where gas is a concern, Dilithium-3 (FIPS 204 Level 3) is available via the --pq-level 3 compiler flag.

CRYSTALS-Kyber-1024 (FIPS 203) — Key Encapsulation

ParameterValue
NIST level5 (256-bit quantum security)
Public key size1,568 bytes
Ciphertext size1,568 bytes
Shared secret size32 bytes
Encapsulation gas60,000
Decapsulation gas65,000

Kyber is used in Covenant for establishing encrypted communication channels between contracts — for example, when doing threshold decryption for ERC-8227 where validators need to exchange key material.

Key Format

PQ public key on-chain storage format:

bytes2600 pq_public_key = [
  bytes2    algorithm_id,   // 0x0001 = Dilithium-5, 0x0002 = Kyber-1024
  bytes2590 key_material,   // algorithm-specific public key
  bytes8    reserved        // must be zero in v1
]

The ERC-8231 registry contract stores a mapping address → pq_public_key. A single address can register one Dilithium key and one Kyber key.

ERC-8231 Registry Interface

{
  "name": "IERC8231PQRegistry",
  "functions": [
    {
      "name": "registerDilithiumKey",
      "inputs": [{"name":"pk","type":"bytes2600"}],
      "outputs": []
    },
    {
      "name": "getDilithiumKey",
      "inputs": [{"name":"account","type":"address"}],
      "outputs": [{"name":"pk","type":"bytes2600"}]
    },
    {
      "name": "verifyDilithiumSignature",
      "inputs": [
        {"name":"account","type":"address"},
        {"name":"message","type":"bytes"},
        {"name":"signature","type":"bytes4627"}
      ],
      "outputs": [{"name":"valid","type":"bool"}]
    }
  ]
}

Using @pq_signed

contract QuantumSafeVault {
    field pq_admin: pq_key
    field treasury: amount
    
    action initialize_pq_admin(pk: pq_key) only deployer {
        pq_admin = pk
    }
    
    // Requires BOTH ECDSA (from 'only admin') AND Dilithium-5 signature
    action withdraw(to: address, amount: amount)
        only admin
        @pq_signed(pq_admin) {
        
        given amount <= treasury or revert_with InsufficientFunds()
        treasury = treasury - amount
        transfer(to, amount)
    }
}

The @pq_signed(pq_admin) guard causes the compiler to:

  1. Read pq_admin from storage
  2. Call the 0x41 (pq_verify) precompile with the signature attached to the transaction
  3. Revert if the signature is invalid or no signature is provided

Transactions to @pq_signed functions must include the PQ signature in the calldata via a special encoding. The Covenant SDK handles this automatically.

Hybrid Classical + PQ Mode

For contracts that need to remain compatible with existing wallets while offering optional PQ security:

action critical_upgrade(new_impl: address) {
    // Accept if EITHER:
    // 1. Classic multisig (3 of 5)
    // 2. PQ signed by quantum_admin
    given (
        multisig_approvals >= 3
        OR pq_verify(quantum_sig, msg_hash, quantum_admin_key)
    )
    proxy_upgrade(new_impl)
}

This “hybrid mode” is recommended for the 2026-2030 transition period.

When to Use PQ Signatures

Use ERC-8231 for:

  • Protocol governance (DAO votes, parameter changes)
  • Treasury management (withdrawals > $1M)
  • Key rotation ceremonies
  • Contracts with >5 year expected lifespan
  • Regulatory-sensitive applications

Skip ERC-8231 for:

  • Simple DeFi operations (trading, providing liquidity)
  • Short-lived contracts
  • High-frequency low-value operations (gas cost is 3-5× ECDSA)

Gas Comparison

OperationECDSADilithium-5Ratio
Key storage64 bytes2,600 bytes40×
Signature storage65 bytes4,627 bytes71×
On-chain verification3,000 gas80,000 gas27×
Calldata cost65×16 = 1,0404,627×16 = 74,03271×

PQ verification on Aster Chain costs ~8,000 pGas (10× cheaper than L1), making it practical for medium-frequency operations.

See Also