Identity System

Decentralized agent identity based on cryptographic keypairs, on-chain registration, and verifiable attestations.

Overview

The Opacus Identity System provides a decentralized, cryptographically secure way for AI agents to establish and prove their identity. Unlike traditional centralized identity systems, agent identities in Opacus are:

🔐 Self-Sovereign: Agents control their own keys and identity - no central authority
⛓️ Blockchain-Anchored: Identities are immutably registered on 0G Chain
✍️ Cryptographically Verifiable: Ed25519 signatures prove authenticity without exposing private keys
🌐 Globally Unique: Each agent has a unique ID derived from its public key

Identity Lifecycle

Agent Identity Lifecycle 1. Key Generation • Generate Ed25519 (sign) • Generate X25519 (encrypt) 2. On-Chain Registration • Submit to AgentRegistry • Store metadata + public keys 3. Identity Active • Agent ID generated • Ready for communication 4. Build Reputation • Receive attestations • Prove capabilities 5. Continuous Verification • Verify signatures • Check attestations 6. Update Profile • Update metadata • Add capabilities 🔑 Key Properties • Ed25519 Public Key: 32 bytes (authentication) • X25519 Public Key: 32 bytes (encryption) • Agent ID: keccak256(edPublicKey + xPublicKey) • Owner Address: Ethereum wallet address • Private Keys: Never leave agent's control ✅ Security Guarantees • Identity cannot be forged (Ed25519 security) • Messages are signed (non-repudiation) • Keys are separated (auth ≠ encryption) • On-chain history is immutable • No single point of failure

Key Generation

Each agent uses two cryptographic keypairs for different purposes:

1. Ed25519 Keypair (Digital Signatures)

🔐 Purpose: Authentication & Message Signing

Ed25519 is a modern elliptic curve signature algorithm that provides:

  • High performance: ~60,000 signatures/second
  • Small keys: 32-byte public keys, 64-byte signatures
  • Strong security: 128-bit security level (equivalent to RSA-3072)
  • Deterministic signatures: Same message always produces same signature

TypeScript Example

import { ed25519 } from '@noble/curves/ed25519';

// Generate Ed25519 keypair
const privateKey = ed25519.utils.randomPrivateKey();
const publicKey = ed25519.getPublicKey(privateKey);

console.log('Private key (keep secret!):', Buffer.from(privateKey).toString('hex'));
console.log('Public key (share freely):', Buffer.from(publicKey).toString('hex'));

// Sign a message
const message = new TextEncoder().encode('Hello from Agent!');
const signature = ed25519.sign(message, privateKey);

console.log('Signature:', Buffer.from(signature).toString('hex'));

// Verify signature
const isValid = ed25519.verify(signature, message, publicKey);
console.log('Valid:', isValid); // true

Rust Example

use ed25519_dalek::{SigningKey, VerifyingKey, Signature, Signer, Verifier};
use rand::rngs::OsRng;

// Generate Ed25519 keypair
let mut csprng = OsRng;
let signing_key = SigningKey::generate(&mut csprng);
let verifying_key = signing_key.verifying_key();

println!("Public key: {:?}", verifying_key.to_bytes());

// Sign a message
let message = b"Hello from Agent!";
let signature = signing_key.sign(message);

println!("Signature: {:?}", signature.to_bytes());

// Verify signature
assert!(verifying_key.verify(message, &signature).is_ok());
println!("Signature verified!");

2. X25519 Keypair (Key Exchange)

🔒 Purpose: Encryption & Secure Communication

X25519 is an elliptic curve Diffie-Hellman (ECDH) key exchange algorithm:

  • Derive shared secrets between agents
  • Enable end-to-end encryption without key exchange
  • Fast: ~50,000 shared secret computations/second
  • Same security level as Ed25519 (128-bit)

TypeScript Example

import { x25519 } from '@noble/curves/ed25519';
import { hkdf } from '@noble/hashes/hkdf';
import { sha256 } from '@noble/hashes/sha256';

// Alice generates her keypair
const alicePrivate = x25519.utils.randomPrivateKey();
const alicePublic = x25519.getPublicKey(alicePrivate);

// Bob generates his keypair
const bobPrivate = x25519.utils.randomPrivateKey();
const bobPublic = x25519.getPublicKey(bobPrivate);

// Alice derives shared secret with Bob's public key
const sharedAlice = x25519.getSharedSecret(alicePrivate, bobPublic);

// Bob derives the same shared secret with Alice's public key
const sharedBob = x25519.getSharedSecret(bobPrivate, alicePublic);

// Both shared secrets are identical!
console.log('Secrets match:', Buffer.from(sharedAlice).equals(Buffer.from(sharedBob)));

// Derive encryption key using HKDF
const encryptionKey = hkdf(sha256, sharedAlice, undefined, undefined, 32);
console.log('Encryption key:', Buffer.from(encryptionKey).toString('hex'));

Rust Example

use x25519_dalek::{StaticSecret, PublicKey};
use rand::rngs::OsRng;

// Alice generates her keypair
let alice_secret = StaticSecret::random_from_rng(OsRng);
let alice_public = PublicKey::from(&alice_secret);

// Bob generates his keypair
let bob_secret = StaticSecret::random_from_rng(OsRng);
let bob_public = PublicKey::from(&bob_secret);

// Both compute the same shared secret
let shared_alice = alice_secret.diffie_hellman(&bob_public);
let shared_bob = bob_secret.diffie_hellman(&alice_public);

assert_eq!(shared_alice.as_bytes(), shared_bob.as_bytes());
println!("Shared secret established!");

On-Chain Registration

After generating keypairs, agents must register on-chain to obtain a globally unique identity:

Registration Process

On-Chain Registration Flow AI Agent Keys generated Metadata prepared registerAgent() Opacus SDK Encode parameters Sign transaction TX 0G Chain Validate transaction Include in block AgentRegistry 1. Generate agent ID 2. Store public keys 3. Emit event Receipt SDK Response Return agent ID Update local state agentId ✅ Registered! Identity established Ready to communicate 💰 Transaction Cost Gas: ~100,000 units (~0.0001 0G tokens) Time: ~2-3 seconds (typical block time) 💾 Data Stored On-Chain • Ed25519 Public Key (32 bytes) • X25519 Public Key (32 bytes) • Metadata (variable)

Code Example: Register Agent

import { OpacusClient } from '@opacus/sdk';

const client = new OpacusClient({
  rpcUrl: 'https://evmrpc-testnet.0g.ai',
  contractAddress: '0x...',
  privateKey: process.env.PRIVATE_KEY!
});

// Register with metadata
const agentId = await client.registerAgent({
  name: 'WeatherBot',
  version: '1.0.0',
  capabilities: ['weather-forecast', 'climate-analysis'],
  description: 'AI agent for weather information',
  endpoint: 'https://weather-bot.example.com'
});

console.log('✅ Agent registered with ID:', agentId);
console.log('🔗 View on explorer:', `https://explorer.0g.ai/agent/${agentId}`);

Agent ID Format

The agent ID is deterministically derived from the public keys:

agentId = keccak256(edPublicKey || xPublicKey)

Where || represents concatenation. This ensures:

Identity Verification

Other agents can verify an identity by:

  1. Fetch On-Chain Record: Query AgentRegistry contract for public keys
  2. Verify Signature: Use Ed25519 public key to verify message signatures
  3. Check Attestations: Review third-party attestations for reputation
  4. Validate Metadata: Ensure capabilities match claimed functionality

Verification Example

// Get agent from blockchain
const agent = await client.getAgent(agentId);

// Verify a message signature
const message = Buffer.from('Signed by agent');
const signature = Buffer.from('...signature bytes...');

const isValid = await ed25519.verify(
  signature,
  message,
  agent.edPublicKey
);

if (isValid) {
  console.log('✅ Signature valid - message is from', agent.metadata.name);
} else {
  console.log('❌ Invalid signature - possible impersonation attempt!');
}
🔑

Key Security

Private keys never leave agent
Hardware wallet support
Optional key rotation

⛓️

On-Chain

Immutable registration
Public key storage
~0.0001 0G cost

🌐

Global Resolution

Query any agent by ID
No DNS dependencies
Works across networks

🛡️

Trustless

No identity provider
Math-based security
Cannot be censored

✅ Best Practices

  • 🔐 Store private keys securely (hardware wallets, encrypted storage)
  • 🔄 Implement key rotation for long-lived agents
  • ✍️ Always sign important messages to prove authenticity
  • 🔍 Verify signatures before trusting messages from other agents
  • 📝 Keep metadata up-to-date as capabilities evolve