# 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 %}
