diff --git a/api/net/sf/briar/api/transport/PacketWriterFactory.java b/api/net/sf/briar/api/transport/PacketWriterFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdb79b0ebd9d1a77d67aaac49ae5dc20d4449481
--- /dev/null
+++ b/api/net/sf/briar/api/transport/PacketWriterFactory.java
@@ -0,0 +1,12 @@
+package net.sf.briar.api.transport;
+
+import java.io.OutputStream;
+
+import javax.crypto.SecretKey;
+
+public interface PacketWriterFactory {
+
+	PacketWriter createPacketWriter(OutputStream out, int transportIdentifier,
+			long connectionNumber, SecretKey macKey, SecretKey tagKey,
+			SecretKey packetKey);
+}
diff --git a/components/net/sf/briar/transport/PacketWriterFactoryImpl.java b/components/net/sf/briar/transport/PacketWriterFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..92ea6ded206318ba6778330b29456e6dfa8f9f1d
--- /dev/null
+++ b/components/net/sf/briar/transport/PacketWriterFactoryImpl.java
@@ -0,0 +1,38 @@
+package net.sf.briar.transport;
+
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
+import net.sf.briar.api.crypto.CryptoComponent;
+import net.sf.briar.api.transport.PacketWriter;
+import net.sf.briar.api.transport.PacketWriterFactory;
+
+import com.google.inject.Inject;
+
+class PacketWriterFactoryImpl implements PacketWriterFactory {
+
+	private final CryptoComponent crypto;
+
+	@Inject
+	public PacketWriterFactoryImpl(CryptoComponent crypto) {
+		this.crypto = crypto;
+	}
+
+	public PacketWriter createPacketWriter(OutputStream out,
+			int transportIdentifier, long connectionNumber, SecretKey macKey,
+			SecretKey tagKey, SecretKey packetKey) {
+		Mac mac = crypto.getMac();
+		try {
+			mac.init(macKey);
+		} catch(InvalidKeyException e) {
+			throw new IllegalArgumentException(e);
+		}
+		PacketEncrypter e = new PacketEncrypterImpl(out, crypto.getTagCipher(),
+				crypto.getPacketCipher(), tagKey, packetKey);
+		return new PacketWriterImpl(e, mac, transportIdentifier,
+				connectionNumber);
+	}
+}
diff --git a/components/net/sf/briar/transport/TransportModule.java b/components/net/sf/briar/transport/TransportModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a138334dffb36d6c6ed8bfa62ef99e62050594e
--- /dev/null
+++ b/components/net/sf/briar/transport/TransportModule.java
@@ -0,0 +1,13 @@
+package net.sf.briar.transport;
+
+import net.sf.briar.api.transport.PacketWriter;
+
+import com.google.inject.AbstractModule;
+
+public class TransportModule extends AbstractModule {
+
+	@Override
+	protected void configure() {
+		bind(PacketWriter.class).to(PacketWriterImpl.class);
+	}
+}