diff --git a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
index 13fbbb23039827f2780b4e808e11c857d2464502..be3d55747f93e0a754f686ab8872101956e6eaff 100644
--- a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
@@ -2,20 +2,21 @@ package net.sf.briar.api.transport;
 
 import java.io.OutputStream;
 
+import net.sf.briar.api.plugins.SegmentSink;
+
 public interface ConnectionWriterFactory {
 
 	/**
-	 * Creates a connection writer for a simplex connection or the initiator's
-	 * side of a duplex connection. The secret is erased before this method
-	 * returns.
+	 * Creates a connection writer for a simplex connection or one side of a
+	 * duplex connection. The secret is erased before this method returns.
 	 */
 	ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
-			byte[] secret);
+			byte[] secret, boolean initiator);
 
 	/**
-	 * Creates a connection writer for the responder's side of a duplex
-	 * connection. The secret is erased before this method returns.
+	 * Creates a connection writer for a simplex connection or one side of a
+	 * duplex connection. The secret is erased before this method returns.
 	 */
-	ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
-			byte[] secret, byte[] tag);
+	ConnectionWriter createConnectionWriter(SegmentSink out, long capacity,
+			byte[] secret, boolean initiator);
 }
diff --git a/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java b/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java
index 75e6554cdf315e219b3af0ef64d85417b3c12354..898cefd8aa08d67abb6ad46bb8b07eaec9ec81fa 100644
--- a/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java
+++ b/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java
@@ -48,6 +48,6 @@ class IncomingDuplexConnection extends DuplexConnection {
 	protected ConnectionWriter createConnectionWriter() throws IOException {
 		return connWriterFactory.createConnectionWriter(
 				transport.getOutputStream(), Long.MAX_VALUE, ctx.getSecret(),
-				tag);
+				false);
 	}
 }
diff --git a/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java b/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java
index aee3b4d83b4b6980e2ca2fc996bac0e6bfd1e97c..ffc60361d98f1ea24f192d1147ff7632c8d9d105 100644
--- a/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java
+++ b/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java
@@ -60,6 +60,7 @@ class OutgoingDuplexConnection extends DuplexConnection {
 				ctx = db.getConnectionContext(contactId, transportIndex);
 		}
 		return connWriterFactory.createConnectionWriter(
-				transport.getOutputStream(), Long.MAX_VALUE, ctx.getSecret());
+				transport.getOutputStream(), Long.MAX_VALUE, ctx.getSecret(),
+				true);
 	}
 }
diff --git a/components/net/sf/briar/protocol/simplex/OutgoingSimplexConnection.java b/components/net/sf/briar/protocol/simplex/OutgoingSimplexConnection.java
index f7e404bf0af56b08812e7e1ccf00ad96e1eaf96b..8d1082f8f1c9a26119cf760e0da377c0871071d9 100644
--- a/components/net/sf/briar/protocol/simplex/OutgoingSimplexConnection.java
+++ b/components/net/sf/briar/protocol/simplex/OutgoingSimplexConnection.java
@@ -62,7 +62,7 @@ class OutgoingSimplexConnection {
 					transportIndex);
 			ConnectionWriter conn = connFactory.createConnectionWriter(
 					transport.getOutputStream(), transport.getCapacity(),
-					ctx.getSecret());
+					ctx.getSecret(), true);
 			OutputStream out = conn.getOutputStream();
 			ProtocolWriter writer = protoFactory.createProtocolWriter(out,
 					transport.shouldFlush());
diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
index f2530acd689777f783563072496a66e3ca7966cd..a3f7f1ed6107731e8a5242a3f5e5a877ca1b335c 100644
--- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
@@ -7,6 +7,7 @@ import javax.crypto.Mac;
 
 import net.sf.briar.api.crypto.CryptoComponent;
 import net.sf.briar.api.crypto.ErasableKey;
+import net.sf.briar.api.plugins.SegmentSink;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
 import net.sf.briar.util.ByteUtils;
@@ -23,23 +24,27 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 	}
 
 	public ConnectionWriter createConnectionWriter(OutputStream out,
-			long capacity, byte[] secret) {
-		return createConnectionWriter(out, capacity, true, secret);
-	}
-
-	public ConnectionWriter createConnectionWriter(OutputStream out,
-			long capacity, byte[] secret, byte[] tag) {
-		// Validate the tag
+			long capacity, byte[] secret, boolean initiator) {
+		// Derive the keys and erase the secret
+		ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
+		ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
+		ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
+		ByteUtils.erase(secret);
+		// Create the encrypter
 		Cipher tagCipher = crypto.getTagCipher();
-		ErasableKey tagKey = crypto.deriveTagKey(secret, true);
-		long segmentNumber = TagEncoder.decodeTag(tag, tagCipher, tagKey);
-		tagKey.erase();
-		if(segmentNumber != 0) throw new IllegalArgumentException();
-		return createConnectionWriter(out, capacity, false, secret);
+		Cipher frameCipher = crypto.getFrameCipher();
+		OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out,
+				capacity, tagCipher, frameCipher, tagKey, frameKey, false);
+		// No error correction
+		OutgoingErrorCorrectionLayer correcter =
+			new NullOutgoingErrorCorrectionLayer(encrypter);
+		// Create the writer
+		Mac mac = crypto.getMac();
+		return new ConnectionWriterImpl(correcter, mac, macKey);
 	}
 
-	private ConnectionWriter createConnectionWriter(OutputStream out,
-			long capacity, boolean initiator, byte[] secret) {
+	public ConnectionWriter createConnectionWriter(SegmentSink out,
+			long capacity, byte[] secret, boolean initiator) {
 		// Derive the keys and erase the secret
 		ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
 		ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
@@ -48,8 +53,9 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 		// Create the encrypter
 		Cipher tagCipher = crypto.getTagCipher();
 		Cipher frameCipher = crypto.getFrameCipher();
-		OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out,
-				capacity, tagCipher, frameCipher, tagKey, frameKey, false);
+		OutgoingEncryptionLayer encrypter =
+			new OutgoingSegmentedEncryptionLayer(out, capacity, tagCipher,
+					frameCipher, tagKey, frameKey, false);
 		// No error correction
 		OutgoingErrorCorrectionLayer correcter =
 			new NullOutgoingErrorCorrectionLayer(encrypter);
diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java
index 45455525034b2f775449722b114160704d3ce4e9..db5f968cef7d1439b74b704942876f2dc069c6d2 100644
--- a/test/net/sf/briar/ProtocolIntegrationTest.java
+++ b/test/net/sf/briar/ProtocolIntegrationTest.java
@@ -136,7 +136,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
 	private byte[] write() throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		ConnectionWriter conn = connectionWriterFactory.createConnectionWriter(
-				out, Long.MAX_VALUE, secret.clone());
+				out, Long.MAX_VALUE, secret.clone(), true);
 		OutputStream out1 = conn.getOutputStream();
 		ProtocolWriter writer = protocolWriterFactory.createProtocolWriter(out1,
 				false);
diff --git a/test/net/sf/briar/transport/ConnectionWriterTest.java b/test/net/sf/briar/transport/ConnectionWriterTest.java
index 6c84bb12d36263a745c9dcf2f7d4a2b53ae5c21d..58ec3a92b1335de557241176945693c61c1c0d02 100644
--- a/test/net/sf/briar/transport/ConnectionWriterTest.java
+++ b/test/net/sf/briar/transport/ConnectionWriterTest.java
@@ -45,7 +45,7 @@ public class ConnectionWriterTest extends BriarTestCase {
 		ByteArrayOutputStream out =
 			new ByteArrayOutputStream(MIN_CONNECTION_LENGTH);
 		ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
-				MIN_CONNECTION_LENGTH, secret);
+				MIN_CONNECTION_LENGTH, secret, true);
 		// Check that the connection writer thinks there's room for a packet
 		long capacity = w.getRemainingCapacity();
 		assertTrue(capacity >= MAX_PACKET_LENGTH);