Technical Details
Zero-Trust Architecture
Honse Farm uses a zero-trust security model where no entity is trusted by default. Every request, whether from client to server or server to server, must be cryptographically signed and verified.
Overview
This architecture ensures that:
- Authenticity: We can prove who sent a request
- Integrity: We can detect if a request was tampered with
- Non-repudiation: The sender cannot deny having sent the request
- Replay protection: Old requests cannot be reused maliciously
Why Zero-Trust?
In a federated system where multiple independent servers communicate, traditional trust models fail. Any server in the federation can potentially be compromised, tampered with, or operated maliciously. We cannot assume:
- A server claiming to be "server1" is actually that server
- A user claiming to be "user@server2" has permission from that server
- Messages haven't been intercepted and modified in transit
- Old messages aren't being replayed by an attacker
- A federated server hasn't been compromised or is acting in bad faith
Zero-trust solves this: Every request carries cryptographic proof of authenticity. Without valid signatures, requests are rejected. Period. Even if a server in the federation is compromised, it cannot forge requests from users or other servers without their private keys.
High-Level Architecture
Three Trust Domains
- Client to Server: Clients sign action requests with their private key
- Server to Server: Servers sign HTTP requests using Ed25519 signatures in HTTP headers
- User Actions on Remote Servers: When Server 1 needs to act on behalf of a user on Server 2, it includes the user's signed request as proof
Cryptographic Foundation
Ed25519 Digital Signatures
All signing uses Ed25519 (Elliptic Curve Digital Signature Algorithm):
- Public/Private Key Pairs: Each client and server has a unique keypair
- Fast: Signature generation and verification are extremely efficient
- Deterministic: Same input always produces the same signature
Key Properties:
- Private keys never leave the owning entity
- Public keys are shared freely
- Signatures prove the holder of the private key signed the exact message
Security Flows
1. Client to Server Authentication
When a client (game plugin) wants to perform an action:
SignedRequest Structure
public record SignedRequest<T>
{
public T Payload { get; } // The actual request data
public string Signature { get; } // Ed25519 signature
public DateTimeOffset Timestamp { get; } // When it was signed
public string Nonce { get; } // Unique request ID (prevents replay)
}
Why This Works:
- Timestamp: Requests older than a threshold (e.g., 5 minutes) are rejected
- Nonce: Each request has a unique ID, duplicate nonces within the time window are rejected
- Signature: Covers the entire payload. Any modification breaks the signature
2. Server to Server Authentication (Federation)
When servers communicate (e.g., Server 1 sending a pairing request to Server 2):
HTTP Signature Components
The signature covers these HTTP elements:
- (request-target):
POST /federation/command - date:
Thu, 14 Oct 2025 12:34:56 GMT - x-server-id:
server1 - digest:
SHA-256=<base64-hash-of-body>
Signature String Example:
(request-target): post /federation/command
date: Thu, 14 Oct 2025 12:34:56 GMT
x-server-id: server1
digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
This string is signed with Server 1's private key, and the signature is sent in the Signature header:
Signature: keyId="server1",algorithm="ed25519",signature="<base64-signature>"
Why This Works:
- Digest: Ensures the body hasn't been modified
- Date: Prevents replay attacks (requests older than X minutes are rejected)
- X-Server-Id: Identifies the signing server
- Request-Target: Prevents signature reuse on different endpoints
3. User Actions Across Federation (Double Verification)
The most complex case: User on Server 1 wants to pair with a user on Server 2.
Why Double Verification?
Server 2 doesn't trust Server 1 to act on behalf of User 1 without proof:
- HTTP Signature: Proves the request came from Server 1
- User SignedRequest: Proves User 1 authorized the action on Server 1
This prevents:
- Server 1 from forging user actions
- Compromised Server 1 from issuing unauthorized commands
- Man-in-the-middle attacks (modified requests break signatures)
Security Properties
What We Protect Against
| Attack Vector | Protection Mechanism |
|---|---|
| Impersonation | Ed25519 signatures. Attacker needs private key |
| Message Tampering | Signature covers entire payload/headers. Modifications break signature |
| Replay Attacks | Timestamp + nonce validation |
| Man-in-the-Middle | Signatures bind to specific content. HTTPS encrypts transport |
| Compromised Server | User signatures prove authorization. Can't forge user actions |
| Rogue Federation Member | Zero-trust model. Each request verified independently |
| Tampered Federation Server | All requests require valid signatures. Compromised server can't forge requests from other entities |
What We Don't Protect Against
- Compromised Private Keys: If a private key is stolen, the attacker can sign requests (key rotation needed)
- Time Synchronization Issues: Clocks must be reasonably accurate (NTP recommended)
- Denial of Service: Signature verification has a cost (rate limiting needed at infrastructure level)
Summary
Honse Farm's zero-trust architecture ensures that every request from any source is cryptographically verified before processing. By combining Ed25519 digital signatures, HTTP Signature standard, SignedRequest pattern, double verification for cross-federation user actions, and replay protection via timestamps and nonces, we create a security model where no entity is trusted without cryptographic proof.
This is essential in a federated system where servers are independently operated and can potentially be compromised or tampered with. The zero-trust model ensures that even if one server in the federation is compromised, it cannot forge requests from users or other servers without their private keys.
The complexity is intentional. It prevents entire classes of attacks and ensures that even if one component is compromised, the system remains secure through defense in depth.
For implementation details, see Zero-Trust Implementation.