# Swarm Authentication

### 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:

{% code title="agentDiscovery.ts" %}

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

{% endcode %}

#### Peer Authentication

Implement secure peer authentication using Ed25519 signatures:

{% code title="authentication.ts" %}

```typescript
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);
    }
}
```

{% endcode %}

#### Secure Channel Establishment

Establish encrypted communication channels between authenticated peers:

{% code title="secureChannel.ts" %}

```typescript
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')
        };
    }
}
```

{% endcode %}

#### Complete Authentication Flow

Implement the full authentication and secure channel establishment process:

{% code title="swarmManager.ts" %}

```typescript
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
        );
    }
}
```

{% endcode %}

### 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:

{% code title="authConfig.ts" %}

```typescript
interface AuthenticationOptions {
    challengeTimeout: number;    // milliseconds
    maxRetries: number;
    backoffFactor: number;
}

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

{% endcode %}

{% hint style="info" %}
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.
{% endhint %}

{% hint style="warning" %}
Always implement proper error handling and logging for authentication failures to maintain system security and aid in troubleshooting.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fxn.world/developers/quick-start/swarm-authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
