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.getAgentSubscribers(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.

Always implement proper error handling and logging for authentication failures to maintain system security and aid in troubleshooting.

Last updated