diff --git a/components/net/sf/briar/protocol/BatchBuilderImpl.java b/components/net/sf/briar/protocol/BatchBuilderImpl.java
index d1fabbeed41fead29e4ec12f0087c548493d7b96..824ac38c56708f4bd082a5356a88695c7f331a15 100644
--- a/components/net/sf/briar/protocol/BatchBuilderImpl.java
+++ b/components/net/sf/briar/protocol/BatchBuilderImpl.java
@@ -1,7 +1,5 @@
 package net.sf.briar.protocol;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.security.KeyPair;
 import java.security.MessageDigest;
 import java.security.Signature;
@@ -10,7 +8,6 @@ import java.util.List;
 
 import net.sf.briar.api.protocol.BatchBuilder;
 import net.sf.briar.api.protocol.Message;
-import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 
 abstract class BatchBuilderImpl implements BatchBuilder {
@@ -19,8 +16,7 @@ abstract class BatchBuilderImpl implements BatchBuilder {
 	protected final KeyPair keyPair;
 	protected final Signature signature;
 	protected final MessageDigest messageDigest;
-
-	private final WriterFactory writerFactory;
+	protected final WriterFactory writerFactory;
 
 	protected BatchBuilderImpl(KeyPair keyPair, Signature signature,
 			MessageDigest messageDigest, WriterFactory writerFactory) {
@@ -33,12 +29,4 @@ abstract class BatchBuilderImpl implements BatchBuilder {
 	public void addMessage(Message m) {
 		messages.add(m);
 	}
-
-	protected byte[] getSignableRepresentation() throws IOException {
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		Writer w = writerFactory.createWriter(out);
-		w.writeList(messages);
-		w.close();
-		return out.toByteArray();
-	}
 }
diff --git a/components/net/sf/briar/protocol/HeaderBuilderImpl.java b/components/net/sf/briar/protocol/HeaderBuilderImpl.java
index 78f19923a322ab6da506225a135b422ee2ac7e1d..d40debd72c46457c59bddf9b5c4ecb2057248023 100644
--- a/components/net/sf/briar/protocol/HeaderBuilderImpl.java
+++ b/components/net/sf/briar/protocol/HeaderBuilderImpl.java
@@ -1,7 +1,5 @@
 package net.sf.briar.protocol;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.security.KeyPair;
 import java.security.MessageDigest;
 import java.security.Signature;
@@ -13,7 +11,6 @@ import java.util.Map;
 import net.sf.briar.api.protocol.BatchId;
 import net.sf.briar.api.protocol.GroupId;
 import net.sf.briar.api.protocol.HeaderBuilder;
-import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 
 abstract class HeaderBuilderImpl implements HeaderBuilder {
@@ -26,8 +23,7 @@ abstract class HeaderBuilderImpl implements HeaderBuilder {
 	protected final KeyPair keyPair;
 	protected final Signature signature;
 	protected final MessageDigest messageDigest;
-
-	private final WriterFactory writerFactory;
+	protected final WriterFactory writerFactory;
 
 	protected HeaderBuilderImpl(KeyPair keyPair, Signature signature,
 			MessageDigest messageDigest, WriterFactory writerFactory) {
@@ -50,14 +46,4 @@ abstract class HeaderBuilderImpl implements HeaderBuilder {
 			this.transports.put(key, transports.get(key));
 		}
 	}
-
-	protected byte[] getSignableRepresentation() throws IOException {
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		Writer w = writerFactory.createWriter(out);
-		w.writeList(acks);
-		w.writeList(subs);
-		w.writeMap(transports);
-		w.close();
-		return out.toByteArray();
-	}
 }
diff --git a/components/net/sf/briar/protocol/IncomingBatchBuilder.java b/components/net/sf/briar/protocol/IncomingBatchBuilder.java
index a07d17bb6968b65f0660c82f0a01ebba6716761f..30f5952fac422e2ef2b39570957b660133555de2 100644
--- a/components/net/sf/briar/protocol/IncomingBatchBuilder.java
+++ b/components/net/sf/briar/protocol/IncomingBatchBuilder.java
@@ -1,5 +1,6 @@
 package net.sf.briar.protocol;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
@@ -9,6 +10,7 @@ import java.security.SignatureException;
 
 import net.sf.briar.api.protocol.Batch;
 import net.sf.briar.api.protocol.BatchId;
+import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 
 public class IncomingBatchBuilder extends BatchBuilderImpl {
@@ -26,14 +28,19 @@ public class IncomingBatchBuilder extends BatchBuilderImpl {
 
 	public Batch build() throws IOException, GeneralSecurityException {
 		if(sig == null) throw new IllegalStateException();
-		byte[] raw = getSignableRepresentation();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		Writer w = writerFactory.createWriter(out);
+		w.writeList(messages);
+		byte[] signable = out.toByteArray();
 		signature.initVerify(keyPair.getPublic());
-		signature.update(raw);
+		signature.update(signable);
 		if(!signature.verify(sig)) throw new SignatureException();
+		w.writeRaw(sig);
+		w.close();
+		byte[] raw = out.toByteArray();
 		messageDigest.reset();
 		messageDigest.update(raw);
-		messageDigest.update(sig);
-		byte[] hash = messageDigest.digest();
-		return new BatchImpl(new BatchId(hash), raw.length, messages, sig);
+		BatchId id = new BatchId(messageDigest.digest());
+		return new BatchImpl(id, raw.length, messages, sig);
 	}
 }
diff --git a/components/net/sf/briar/protocol/IncomingHeaderBuilder.java b/components/net/sf/briar/protocol/IncomingHeaderBuilder.java
index 0c60a82f1c5d09a9884f5f0abf6e9dfcbd5d13f9..e83b07b8cfb6b1d57f52e2c10cf723cd56a5b14d 100644
--- a/components/net/sf/briar/protocol/IncomingHeaderBuilder.java
+++ b/components/net/sf/briar/protocol/IncomingHeaderBuilder.java
@@ -1,5 +1,6 @@
 package net.sf.briar.protocol;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
@@ -13,6 +14,7 @@ import net.sf.briar.api.protocol.BatchId;
 import net.sf.briar.api.protocol.BundleId;
 import net.sf.briar.api.protocol.GroupId;
 import net.sf.briar.api.protocol.Header;
+import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 
 class IncomingHeaderBuilder extends HeaderBuilderImpl {
@@ -30,17 +32,23 @@ class IncomingHeaderBuilder extends HeaderBuilderImpl {
 
 	public Header build() throws IOException, GeneralSecurityException {
 		if(sig == null) throw new IllegalStateException();
-		byte[] raw = getSignableRepresentation();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		Writer w = writerFactory.createWriter(out);
+		w.writeList(acks);
+		w.writeList(subs);
+		w.writeMap(transports);
+		byte[] signable = out.toByteArray();
 		signature.initVerify(keyPair.getPublic());
-		signature.update(raw);
+		signature.update(signable);
 		if(!signature.verify(sig)) throw new SignatureException();
+		w.writeRaw(sig);
+		w.close();
+		byte[] raw = out.toByteArray();
 		messageDigest.reset();
 		messageDigest.update(raw);
-		messageDigest.update(sig);
-		byte[] hash = messageDigest.digest();
+		BundleId id = new BundleId(messageDigest.digest());
 		Set<BatchId> ackSet = new HashSet<BatchId>(acks);
 		Set<GroupId> subSet = new HashSet<GroupId>(subs);
-		return new HeaderImpl(new BundleId(hash), raw.length, ackSet, subSet,
-				transports, sig);
+		return new HeaderImpl(id, raw.length, ackSet, subSet, transports, sig);
 	}
 }
diff --git a/components/net/sf/briar/protocol/OutgoingBatchBuilder.java b/components/net/sf/briar/protocol/OutgoingBatchBuilder.java
index bc0d673f3fab10bfb82006702d7fa9581feb1b48..118886098db5e273786f1cac7944260471d6d3ed 100644
--- a/components/net/sf/briar/protocol/OutgoingBatchBuilder.java
+++ b/components/net/sf/briar/protocol/OutgoingBatchBuilder.java
@@ -1,5 +1,6 @@
 package net.sf.briar.protocol;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
@@ -8,6 +9,7 @@ import java.security.Signature;
 
 import net.sf.briar.api.protocol.Batch;
 import net.sf.briar.api.protocol.BatchId;
+import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 
 public class OutgoingBatchBuilder extends BatchBuilderImpl {
@@ -22,14 +24,19 @@ public class OutgoingBatchBuilder extends BatchBuilderImpl {
 	}
 
 	public Batch build() throws IOException, GeneralSecurityException {
-		byte[] raw = getSignableRepresentation();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		Writer w = writerFactory.createWriter(out);
+		w.writeList(messages);
+		byte[] signable = out.toByteArray();
 		signature.initSign(keyPair.getPrivate());
-		signature.update(raw);
+		signature.update(signable);
 		byte[] sig = signature.sign();
+		w.writeRaw(sig);
+		w.close();
+		byte[] raw = out.toByteArray();
 		messageDigest.reset();
 		messageDigest.update(raw);
-		messageDigest.update(sig);
-		byte[] hash = messageDigest.digest();
-		return new BatchImpl(new BatchId(hash), raw.length, messages, sig);
+		BatchId id = new BatchId(messageDigest.digest());
+		return new BatchImpl(id, raw.length, messages, sig);
 	}
 }
diff --git a/components/net/sf/briar/protocol/OutgoingHeaderBuilder.java b/components/net/sf/briar/protocol/OutgoingHeaderBuilder.java
index df735ddaa0b6ded4b7f4c8f653acdbe0ef5216d7..970624defcde4069d2e26771a1b086dc103f64b0 100644
--- a/components/net/sf/briar/protocol/OutgoingHeaderBuilder.java
+++ b/components/net/sf/briar/protocol/OutgoingHeaderBuilder.java
@@ -1,5 +1,6 @@
 package net.sf.briar.protocol;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
@@ -12,6 +13,7 @@ import net.sf.briar.api.protocol.BatchId;
 import net.sf.briar.api.protocol.BundleId;
 import net.sf.briar.api.protocol.GroupId;
 import net.sf.briar.api.protocol.Header;
+import net.sf.briar.api.serial.Writer;
 import net.sf.briar.api.serial.WriterFactory;
 
 public class OutgoingHeaderBuilder extends HeaderBuilderImpl {
@@ -26,17 +28,23 @@ public class OutgoingHeaderBuilder extends HeaderBuilderImpl {
 	}
 
 	public Header build() throws IOException, GeneralSecurityException {
-		byte[] raw = getSignableRepresentation();
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		Writer w = writerFactory.createWriter(out);
+		w.writeList(acks);
+		w.writeList(subs);
+		w.writeMap(transports);
+		byte[] signable = out.toByteArray();
 		signature.initSign(keyPair.getPrivate());
-		signature.update(raw);
+		signature.update(signable);
 		byte[] sig = signature.sign();
+		w.writeRaw(sig);
+		w.close();
+		byte[] raw = out.toByteArray();
 		messageDigest.reset();
 		messageDigest.update(raw);
-		messageDigest.update(sig);
-		byte[] hash = messageDigest.digest();
+		BundleId id = new BundleId(messageDigest.digest());
 		Set<BatchId> ackSet = new HashSet<BatchId>(acks);
 		Set<GroupId> subSet = new HashSet<GroupId>(subs);
-		return new HeaderImpl(new BundleId(hash), raw.length, ackSet, subSet,
-				transports, sig);
+		return new HeaderImpl(id, raw.length, ackSet, subSet, transports, sig);
 	}
 }