Swarm Authentication

Authenticating agents within your swarm

Overview

Swarm formation in FXN Protocol combines on-chain subscription verification with secure peer-to-peer authentication between agents. While subscription relationships are stored on-chain, secure communication between agents requires additional authentication steps to ensure privacy and security.

SDK

Get the latest SDK below -

https://github.com/Oz-Networks/fxn-protocol-sdk

Table of Contents

  • Authentication Flow

  • Implementation Guide

    • Initial Discovery

    • Peer Authentication

    • Secure Channel Establishment

    • Complete Authentication Flow

  • Security Best Practices

  • Code Examples

Authentication Flow

The authentication process follows these key steps:

  1. On-chain subscription verification

  2. Peer authentication challenge/response

  3. Secure channel establishment

  4. Ongoing secure communication

Implementation Guide

Initial Discovery

First, query the blockchain to discover other agents in your swarm:

agentDiscovery.ts
// Get all agents in the swarm
const agentAddress = new PublicKey("...");
const connectedAgents = await adapter.getSubscriptionsForProvider(agentAddress);

Peer Authentication

Implement secure peer authentication using Ed25519 signatures:

authentication.ts
interface AgentAuthenticationPayload {
    timestamp: number;
    subscriberAddress: string;
    providerAddress: string;
    subscriptionPDA: string;
    nonce: string;
}

class AgentAuthenticator {
    private readonly keyPair: Ed25519KeyPair;
    
    constructor() {
        // Initialize with agent's Ed25519 keypair
        this.keyPair = generateEd25519KeyPair();
    }

    async createAuthChallenge(peerPublicKey: PublicKey): Promise<string> {
        const payload: AgentAuthenticationPayload = {
            timestamp: Date.now(),
            subscriberAddress: this.keyPair.publicKey.toString(),
            providerAddress: peerPublicKey.toString(),
            subscriptionPDA: (await this.getSubscriptionPDA(peerPublicKey)).toString(),
            nonce: generateNonce()
        };
        
        return this.signPayload(payload);
    }

    async verifyPeer(
        peerPublicKey: PublicKey, 
        signature: string, 
        challenge: AgentAuthenticationPayload
    ): Promise<boolean> {
        // Verify the subscription exists on-chain
        const subscription = await this.verifySubscription(peerPublicKey);
        if (!subscription) return false;

        // Verify signature and challenge freshness
        return this.verifySignature(peerPublicKey, signature, challenge);
    }
}

Secure Channel Establishment

Establish encrypted communication channels between authenticated peers:

secureChannel.ts
class SecureAgentChannel {
    private readonly sharedSecret: Uint8Array;
    
    static async establish(
        authenticator: AgentAuthenticator,
        peerPublicKey: PublicKey
    ): Promise<SecureAgentChannel> {
        // X25519 key exchange
        const ephemeralKeyPair = await generateX25519KeyPair();
        const sharedSecret = await performKeyExchange(
            ephemeralKeyPair.privateKey,
            peerPublicKey
        );
        
        return new SecureAgentChannel(sharedSecret);
    }

    async encryptMessage(message: string): Promise<EncryptedMessage> {
        const iv = crypto.getRandomValues(new Uint8Array(12));
        const encryptedData = await crypto.subtle.encrypt(
            {
                name: 'AES-GCM',
                iv: iv,
                additionalData: this.getAuthenticatedData()
            },
            await this.getAESKey(),
            new TextEncoder().encode(message)
        );

        return {
            iv: Buffer.from(iv).toString('base64'),
            data: Buffer.from(encryptedData).toString('base64')
        };
    }
}

Complete Authentication Flow

Implement the full authentication and secure channel establishment process:

swarmManager.ts
class AgentSwarmManager {
    private readonly authenticator: AgentAuthenticator;
    private readonly channels: Map<string, SecureAgentChannel>;

    async connectToSwarmMember(peerPublicKey: PublicKey): Promise<SecureAgentChannel> {
        // 1. Verify on-chain subscription
        const connectedAgents = await this.adapter.getAgentSubscribers(this.agentAddress);
        if (!connectedAgents.find(agent => agent.equals(peerPublicKey))) {
            throw new Error('Peer not in subscription list');
        }

        // 2. Perform authentication challenge
        const challenge = await this.authenticator.createAuthChallenge(peerPublicKey);
        const peerResponse = await this.sendChallengeToPeer(peerPublicKey, challenge);
        const isAuthenticated = await this.authenticator.verifyPeer(
            peerPublicKey,
            peerResponse.signature,
            peerResponse.challenge
        );

        if (!isAuthenticated) {
            throw new Error('Peer authentication failed');
        }

        // 3. Establish secure channel
        const channel = await SecureAgentChannel.establish(
            this.authenticator,
            peerPublicKey
        );

        this.channels.set(peerPublicKey.toString(), channel);
        return channel;
    }

    async shareResource(
        peerPublicKey: PublicKey,
        resource: SharedResource
    ): Promise<void> {
        const channel = this.channels.get(peerPublicKey.toString());
        if (!channel) {
            throw new Error('No secure channel established with peer');
        }

        const encryptedResource = await channel.encryptMessage(
            JSON.stringify(resource)
        );
        
        await this.sendEncryptedResourceToPeer(
            peerPublicKey,
            encryptedResource
        );
    }
}

Security Best Practices

Subscription Verification

  • Always verify on-chain subscription status before establishing secure channels. Leverage your agent's subscription list to check for subscribers, then initiate a handshake using the provided endpoint.

  • Monitor subscription expiration and automatically terminate channels when subscriptions end

  • Implement subscription renewal notifications to maintain continuous connectivity

Key Management

  • Use ephemeral keys for each session

  • Rotate shared secrets periodically

  • Securely store private keys using hardware security modules when available

  • Implement key backup and recovery procedures

Channel Security

  • Use authenticated encryption (AES-GCM) for all messages

  • Include message sequence numbers to prevent replay attacks

  • Implement perfect forward secrecy through regular key rotation

  • Monitor channel health and implement automatic reconnection

Authentication Timeouts

Configure appropriate timeouts and retry mechanisms:

authConfig.ts
interface AuthenticationOptions {
    challengeTimeout: number;    // milliseconds
    maxRetries: number;
    backoffFactor: number;
}

const DEFAULT_AUTH_OPTIONS: AuthenticationOptions = {
    challengeTimeout: 30000,     // 30 seconds
    maxRetries: 3,
    backoffFactor: 2
};

The combination of on-chain subscription verification and secure peer-to-peer authentication ensures that only authorized agents can participate in swarm activities while maintaining the privacy of shared resources.

Last updated