Building Private Message Boards on Swarm Using the Bchan Protocol: A Complete Guide
The Bchan protocol leverages Swarm's encrypted feeds and content-addressed storage to create fully decentralized, private message boards where only secret key holders can read or write messages.
Building private message boards on Swarm using the Bchan protocol enables developers to deploy censorship-resistant communication platforms without centralized infrastructure. The Bchan protocol, curated in the ethersphere/awesome-swarm repository under README.md, implements an encrypted feed system on top of Swarm's Bee nodes to provide append-only message logs that remain private and tamper-proof. While the Awesome Swarm list provides the entry point, the actual implementation resides at https://github.com/bzz/bchan and the live UI is hosted at https://bchan.bzz.limo/.
How Bchan Works on Swarm
Bchan operates as a layer-2 protocol on Swarm, utilizing the network's epoch-based feeds, manifests, and chunk storage to maintain private message boards. The architecture ensures that only participants possessing the board's secret key can decrypt content, while the feed structure guarantees message ordering and authenticity.
Core Components
| Component | Role | Swarm Implementation |
|---|---|---|
| Bee node | The Swarm client that stores and serves data chunks. | Runs as a local Docker instance or connects to a public gateway like https://gateway.ethswarm.org. |
| Encrypted feeds | Append-only logs for board messages. | Implemented as epoch-based manifests that point to the latest message chunk. Bchan uses encrypted feeds so only private key holders can read or write. |
| Manifests | Indirect pointers to the current feed version. | Each new message creates a manifest referencing the fresh chunk, then updates the feed head. |
| Client-side encryption | Guarantees message privacy. | Bchan encrypts payloads using AES-GCM before upload, ensuring the Swarm network never processes plaintext. |
| Bzz URLs | Human-readable board identifiers. | Boards are addressed via bzz://<board-hash>/, resolving to the latest manifest through the feed. |
Message Flow
When a user publishes a new post, the Bchan client executes the following sequence:
- Encrypts the message using the board's 32-byte AES secret key.
- Uploads the ciphertext as a Swarm chunk via the Bee HTTP API (
POST /chunksorPOST /bytes). - Creates a new manifest that references the uploaded chunk.
- Updates the board's feed head to the new manifest hash using the epoch feed mechanism.
Reading a board reverses this process:
- Resolves the board's feed to obtain the latest manifest hash.
- Downloads the referenced chunk from Swarm.
- Decrypts the payload using the board secret.
Because the feed is cryptographically signed with the board owner's private key, participants can verify message authenticity, while the encryption ensures confidentiality.
Implementing Private Message Boards with Bchan
Developers can deploy Bchan boards either through the pre-built web interface or programmatically using the Bee JavaScript API.
Prerequisites: Running a Bee Node
To interact with Swarm directly, run a local Bee node using Docker:
docker run -p 1633:1633 ethersphere/bee:latest
Alternatively, use the public gateway at https://gateway.ethswarm.org for development purposes, though running your own node provides better privacy and performance.
Creating a Board via the Web UI
The simplest method uses the hosted Bchan interface:
- Navigate to
https://bchan.bzz.limo/. - The UI automatically connects to the default public gateway.
- Click Create Board.
- Enter a board name and generate a board secret (the UI handles local key generation).
- The UI uploads an initial empty manifest and registers a new encrypted feed.
- Share the resulting
bzz://<board-hash>/URL and the secret key securely with participants.
Programmatic Access with bee-js
For custom applications, use the bee-js library to implement Bchan-style boards. The following Node.js example demonstrates the complete workflow:
// npm install @ethersphere/bee-js
import { Bee } from '@ethersphere/bee-js';
import crypto from 'crypto';
// ---------------------------------------------------
// 1️⃣ Initialise Bee client (local node or public gateway)
const bee = new Bee('http://localhost:1633'); // or https://gateway.ethswarm.org
// ---------------------------------------------------
// 2️⃣ Generate board secret (32‑byte AES key) and feed topic
const boardSecret = crypto.randomBytes(32); // keep this secret!
const feedTopic = crypto.randomBytes(32); // unique identifier for the board
// ---------------------------------------------------
// 3️⃣ Helper: encrypt a message with the board secret
function encryptMessage(text) {
const iv = crypto.randomBytes(12); // AES‑GCM nonce
const cipher = crypto.createCipheriv('aes-256-gcm', boardSecret, iv);
const ciphertext = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
// Store iv|tag|ciphertext
return Buffer.concat([iv, tag, ciphertext]);
}
// ---------------------------------------------------
// 4️⃣ Helper: publish a new message to the board feed
async function publishMessage(text) {
// 4a️⃣ encrypt
const encrypted = encryptMessage(text);
// 4b️⃣ upload encrypted chunk
const { reference } = await bee.uploadData(encrypted);
// 4c️⃣ create a manifest that points to the chunk
const manifest = await bee.createFeedManifest(reference, { feedType: 'epoch', topic: feedTopic });
// 4d️⃣ update the feed head (epoch feed)
await bee.setFeedContent('epoch', feedTopic, reference, { signer: bee.signer });
console.log('Message published, manifest hash:', manifest.reference);
}
// ---------------------------------------------------
// 5️⃣ Helper: read the latest message from the board
async function readLatestMessage() {
// 5a️⃣ resolve feed head (latest manifest hash)
const head = await bee.getFeedContent('epoch', feedTopic, { signer: bee.signer });
// 5b️⃣ download the referenced chunk (encrypted payload)
const encrypted = await bee.downloadData(head.reference);
// 5c️⃣ decrypt
const iv = encrypted.slice(0, 12);
const tag = encrypted.slice(12, 28);
const ciphertext = encrypted.slice(28);
const decipher = crypto.createDecipheriv('aes-256-gcm', boardSecret, iv);
decipher.setAuthTag(tag);
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
console.log('Latest message:', plaintext.toString('utf8'));
}
// ---------------------------------------------------
// Example usage
await publishMessage('Hello, Swarm Bchan board! 🚀');
await readLatestMessage();
Key Implementation Details
- Feed topic (
feedTopic) serves as the unique board identifier within Swarm's feed system. - Board secret (
boardSecret) is the 32-byte AES key that grants read/write access—distribute this securely to participants. - AES-GCM provides authenticated encryption; the code stores the 12-byte IV, 16-byte authentication tag, and ciphertext together.
- Bee client abstracts chunk upload (
uploadData), manifest creation (createFeedManifest), and feed updates (setFeedContent).
Security and Privacy Model
Bchan's security guarantees stem from client-side encryption and Swarm's decentralized architecture. Because encryption occurs before data touches the network, Swarm nodes store only opaque ciphertext—the network never processes plaintext or possesses decryption keys.
The epoch-based feed ensures message ordering and integrity. Each update is signed with the board owner's private key, allowing readers to verify authenticity while preventing tampering. However, feed metadata remains public—observers can see that a board exists and when updates occur, but cannot decrypt content without the board secret.
For enhanced privacy, run a local Bee node rather than relying on public gateways. This prevents third-party gateways from logging your IP address alongside feed access patterns.
Summary
Building private message boards on Swarm using the Bchan protocol provides a robust, zero-trust alternative to centralized forums:
- Zero-knowledge storage: AES-GCM encryption ensures Swarm nodes never handle plaintext.
- Decentralized feeds: Epoch-based manifests maintain ordered, authenticated message logs without servers.
- Flexible deployment: Use the hosted UI at
https://bchan.bzz.limo/or integrate programmatically viabee-js. - Content-addressed integrity: Every message is immutable and verifiable through Swarm's chunking layer.
Frequently Asked Questions
What is the Bchan protocol and how does it ensure privacy?
The Bchan protocol is a layer-2 application built on Swarm that implements encrypted, append-only message boards. It ensures privacy by encrypting all content client-side using AES-GCM before uploading to Swarm, ensuring that only holders of the 32-byte board secret can decrypt messages. The protocol uses Swarm's private feeds to prevent unauthorized writing, while the underlying chunks remain opaque to storage providers.
How does Bchan differ from traditional centralized message boards?
Unlike centralized forums that store plaintext on servers controlled by single entities, Bchan stores encrypted data across Swarm's distributed network of Bee nodes. There is no central server to seize or censor; the board exists as long as at least one Swarm node retains the encrypted chunks. Additionally, the feed mechanism provides cryptographic proof of message authenticity without requiring user accounts or email registration.
What are the hardware requirements for running a private Bchan board?
Participants can access Bchan boards through a web browser using the public UI at https://bchan.bzz.limo/ without any local infrastructure. However, for maximum privacy and autonomy, operators should run a local Bee node using Docker, which requires approximately 2GB RAM and 20GB storage for testnet operation, or more for mainnet participation. The bee-js library allows developers to interact with either local nodes or public gateways like https://gateway.ethswarm.org.
How can I programmatically create and manage Bchan boards?
Developers can use the bee-js JavaScript library to implement Bchan functionality by initializing a Bee client, generating a 32-byte board secret for AES-GCM encryption, and creating an epoch-based feed with a unique topic. The workflow involves encrypting messages client-side, uploading ciphertext via bee.uploadData(), creating manifests with bee.createFeedManifest(), and updating the feed head using bee.setFeedContent(). Reading messages requires resolving the feed head, downloading the referenced chunk, and decrypting with the shared board secret.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →