diff --git a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
index a38433f311e324066248a455671078095a0fec57..6bd289e3eeda0c9583f5c5ea3f2a9a16194e3465 100644
--- a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
@@ -23,6 +23,7 @@ import org.briarproject.android.identity.LocalAuthorItemComparator;
 import org.briarproject.android.identity.LocalAuthorSpinnerAdapter;
 import org.briarproject.android.util.CommonLayoutParams;
 import org.briarproject.android.util.LayoutUtils;
+import org.briarproject.api.FormatException;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.CryptoExecutor;
 import org.briarproject.api.crypto.KeyParser;
@@ -39,7 +40,6 @@ import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
 
-import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.util.Collection;
 import java.util.concurrent.Executor;
@@ -281,7 +281,7 @@ implements OnItemSelectedListener, OnClickListener {
 					}
 				} catch (GeneralSecurityException e) {
 					throw new RuntimeException(e);
-				} catch (IOException e) {
+				} catch (FormatException e) {
 					throw new RuntimeException(e);
 				}
 				storePost(p);
diff --git a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
index 3bcfd7b7d0db546d0358b6660e58cf80fdb80138..e05edc8831b3538458c44175e8a005d59d56d878 100644
--- a/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
+++ b/briar-api/src/org/briarproject/api/forum/ForumPostFactory.java
@@ -1,21 +1,21 @@
 package org.briarproject.api.forum;
 
+import org.briarproject.api.FormatException;
 import org.briarproject.api.crypto.PrivateKey;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
 
-import java.io.IOException;
 import java.security.GeneralSecurityException;
 
 public interface ForumPostFactory {
 
 	ForumPost createAnonymousPost(GroupId groupId, long timestamp,
 			MessageId parent, String contentType, byte[] body)
-			throws IOException, GeneralSecurityException;
+			throws FormatException;
 
 	ForumPost createPseudonymousPost(GroupId groupId, long timestamp,
 			MessageId parent, Author author, String contentType, byte[] body,
-			PrivateKey privateKey) throws IOException,
+			PrivateKey privateKey) throws FormatException,
 			GeneralSecurityException;
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
index c598dc1c3162d45483f79fb76aa66bcd5abcfa57..c3c2067f19170e3a5b41cd515deab31ad5d82b54 100644
--- a/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumPostFactoryImpl.java
@@ -1,21 +1,19 @@
 package org.briarproject.forum;
 
+import org.briarproject.api.FormatException;
+import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.PrivateKey;
 import org.briarproject.api.crypto.Signature;
-import org.briarproject.api.data.BdfWriter;
-import org.briarproject.api.data.BdfWriterFactory;
+import org.briarproject.api.data.BdfList;
 import org.briarproject.api.forum.ForumPost;
 import org.briarproject.api.forum.ForumPostFactory;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
-import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.security.GeneralSecurityException;
 
 import javax.inject.Inject;
@@ -26,46 +24,33 @@ import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENG
 class ForumPostFactoryImpl implements ForumPostFactory {
 
 	private final CryptoComponent crypto;
-	private final MessageFactory messageFactory;
-	private final BdfWriterFactory bdfWriterFactory;
+	private final ClientHelper clientHelper;
 
 	@Inject
-	ForumPostFactoryImpl(CryptoComponent crypto, MessageFactory messageFactory,
-			BdfWriterFactory bdfWriterFactory) {
+	ForumPostFactoryImpl(CryptoComponent crypto, ClientHelper clientHelper) {
 		this.crypto = crypto;
-		this.messageFactory = messageFactory;
-		this.bdfWriterFactory = bdfWriterFactory;
+		this.clientHelper = clientHelper;
 	}
 
 	@Override
 	public ForumPost createAnonymousPost(GroupId groupId, long timestamp,
 			MessageId parent, String contentType, byte[] body)
-			throws IOException, GeneralSecurityException {
+			throws FormatException {
 		// Validate the arguments
 		if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH)
 			throw new IllegalArgumentException();
 		if (body.length > MAX_FORUM_POST_BODY_LENGTH)
 			throw new IllegalArgumentException();
-		// Serialise the message to a buffer
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		BdfWriter w = bdfWriterFactory.createWriter(out);
-		w.writeListStart();
-		if (parent == null) w.writeNull();
-		else w.writeRaw(parent.getBytes());
-		w.writeNull(); // No author
-		w.writeString(contentType);
-		w.writeRaw(body);
-		w.writeNull(); // No signature
-		w.writeListEnd();
-		Message m = messageFactory.createMessage(groupId, timestamp,
-				out.toByteArray());
+		// Serialise the message
+		BdfList message = BdfList.of(parent, null, contentType, body, null);
+		Message m = clientHelper.createMessage(groupId, timestamp, message);
 		return new ForumPost(m, parent, null, contentType);
 	}
 
 	@Override
 	public ForumPost createPseudonymousPost(GroupId groupId, long timestamp,
 			MessageId parent, Author author, String contentType, byte[] body,
-			PrivateKey privateKey) throws IOException,
+			PrivateKey privateKey) throws FormatException,
 			GeneralSecurityException {
 		// Validate the arguments
 		if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH)
@@ -73,42 +58,19 @@ class ForumPostFactoryImpl implements ForumPostFactory {
 		if (body.length > MAX_FORUM_POST_BODY_LENGTH)
 			throw new IllegalArgumentException();
 		// Serialise the data to be signed
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		BdfWriter w = bdfWriterFactory.createWriter(out);
-		w.writeListStart();
-		w.writeRaw(groupId.getBytes());
-		w.writeLong(timestamp);
-		if (parent == null) w.writeNull();
-		else w.writeRaw(parent.getBytes());
-		writeAuthor(w, author);
-		w.writeString(contentType);
-		w.writeRaw(body);
-		w.writeListEnd();
+		BdfList authorList = BdfList.of(author.getName(),
+				author.getPublicKey());
+		BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
+				contentType, body);
 		// Generate the signature
 		Signature signature = crypto.getSignature();
 		signature.initSign(privateKey);
-		signature.update(out.toByteArray());
+		signature.update(clientHelper.toByteArray(signed));
 		byte[] sig = signature.sign();
 		// Serialise the signed message
-		out.reset();
-		w = bdfWriterFactory.createWriter(out);
-		w.writeListStart();
-		if (parent == null) w.writeNull();
-		else w.writeRaw(parent.getBytes());
-		writeAuthor(w, author);
-		w.writeString(contentType);
-		w.writeRaw(body);
-		w.writeRaw(sig);
-		w.writeListEnd();
-		Message m = messageFactory.createMessage(groupId, timestamp,
-				out.toByteArray());
+		BdfList message = BdfList.of(parent, authorList, contentType, body,
+				sig);
+		Message m = clientHelper.createMessage(groupId, timestamp, message);
 		return new ForumPost(m, parent, author, contentType);
 	}
-
-	private void writeAuthor(BdfWriter w, Author a) throws IOException {
-		w.writeListStart();
-		w.writeString(a.getName());
-		w.writeRaw(a.getPublicKey());
-		w.writeListEnd();
-	}
 }