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:
On-chain subscription verification
Peer authentication challenge/response
Secure channel establishment
Ongoing secure communication
Implementation Guide
Initial Discovery
First, query the blockchain to discover other agents in your swarm:
// 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:
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:
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:
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:
interface AuthenticationOptions {
challengeTimeout: number; // milliseconds
maxRetries: number;
backoffFactor: number;
}
const DEFAULT_AUTH_OPTIONS: AuthenticationOptions = {
challengeTimeout: 30000, // 30 seconds
maxRetries: 3,
backoffFactor: 2
};
Always implement proper error handling and logging for authentication failures to maintain system security and aid in troubleshooting.
Last updated