From 7ed747b2a310b1d3e8ef89f70ad749fa7887b227 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Wed, 7 Sep 2011 17:21:52 +0100
Subject: [PATCH] Added an initiator flag (bit 31) to the IV.

The flag is used to distinguish between the initiator and responder
directions of a stream-mode connection, allowing them to use the same
connection number without risking IV reuse.

The flag is also raised for batch-mode connections, which only have
one direction.
---
 .../transport/ConnectionReaderFactory.java    |  4 +--
 .../transport/ConnectionWriterFactory.java    |  4 +--
 .../transport/ConnectionDecrypterImpl.java    | 15 ++++------
 .../transport/ConnectionEncrypterImpl.java    | 29 ++++++++-----------
 .../ConnectionReaderFactoryImpl.java          |  5 ++--
 .../transport/ConnectionRecogniserImpl.java   |  2 +-
 .../ConnectionWriterFactoryImpl.java          |  7 +++--
 .../net/sf/briar/transport/IvEncoder.java     | 18 ++++--------
 test/net/sf/briar/FileReadWriteTest.java      |  4 +--
 .../ConnectionDecrypterImplTest.java          | 26 ++++++++++-------
 .../ConnectionEncrypterImplTest.java          | 26 ++++++++++++-----
 .../ConnectionRecogniserImplTest.java         |  2 +-
 .../briar/transport/FrameReadWriteTest.java   | 19 ++++++++----
 13 files changed, 85 insertions(+), 76 deletions(-)

diff --git a/api/net/sf/briar/api/transport/ConnectionReaderFactory.java b/api/net/sf/briar/api/transport/ConnectionReaderFactory.java
index 536123f48e..01498fb9c1 100644
--- a/api/net/sf/briar/api/transport/ConnectionReaderFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionReaderFactory.java
@@ -4,6 +4,6 @@ import java.io.InputStream;
 
 public interface ConnectionReaderFactory {
 
-	ConnectionReader createConnectionReader(InputStream in, int transportId,
-			long connection, byte[] secret);
+	ConnectionReader createConnectionReader(InputStream in, boolean initiator,
+			int transportId, long connection, byte[] secret);
 }
diff --git a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
index 737096bfe8..696616dfb3 100644
--- a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
@@ -4,6 +4,6 @@ import java.io.OutputStream;
 
 public interface ConnectionWriterFactory {
 
-	ConnectionWriter createConnectionWriter(OutputStream out, int transportId,
-			long connection, byte[] secret);
+	ConnectionWriter createConnectionWriter(OutputStream out, boolean initiator,
+			int transportId, long connection, byte[] secret);
 }
diff --git a/components/net/sf/briar/transport/ConnectionDecrypterImpl.java b/components/net/sf/briar/transport/ConnectionDecrypterImpl.java
index 9e74fe792b..77f62df6de 100644
--- a/components/net/sf/briar/transport/ConnectionDecrypterImpl.java
+++ b/components/net/sf/briar/transport/ConnectionDecrypterImpl.java
@@ -20,8 +20,6 @@ import javax.crypto.spec.IvParameterSpec;
 class ConnectionDecrypterImpl extends FilterInputStream
 implements ConnectionDecrypter {
 
-	private final int transportId;
-	private final long connection;
 	private final Cipher frameCipher;
 	private final SecretKey frameKey;
 	private final byte[] buf, iv;
@@ -30,15 +28,13 @@ implements ConnectionDecrypter {
 	private long frame = 0L;
 	private boolean betweenFrames = true;
 
-	ConnectionDecrypterImpl(InputStream in, int transportId, long connection,
-			Cipher frameCipher, SecretKey frameKey) {
+	ConnectionDecrypterImpl(InputStream in, boolean initiator, int transportId,
+			long connection, Cipher frameCipher, SecretKey frameKey) {
 		super(in);
-		this.transportId = transportId;
-		this.connection = connection;
 		this.frameCipher = frameCipher;
 		this.frameKey = frameKey;
 		buf = new byte[IV_LENGTH];
-		iv = new byte[IV_LENGTH];
+		iv = IvEncoder.encodeIv(initiator, transportId, connection);
 	}
 
 	public InputStream getInputStream() {
@@ -132,8 +128,7 @@ implements ConnectionDecrypter {
 	private void initialiseCipher() {
 		assert betweenFrames;
 		if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
-		IvEncoder.encodeIv(iv, transportId, connection, frame);
-		// Use the plaintext IV to initialise the frame cipher
+		IvEncoder.updateIv(iv, frame);
 		IvParameterSpec ivSpec = new IvParameterSpec(iv);
 		try {
 			frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec);
@@ -145,4 +140,4 @@ implements ConnectionDecrypter {
 		frame++;
 		betweenFrames = false;
 	}
-}
+}
\ No newline at end of file
diff --git a/components/net/sf/briar/transport/ConnectionEncrypterImpl.java b/components/net/sf/briar/transport/ConnectionEncrypterImpl.java
index ad1d2d7285..17454fc98a 100644
--- a/components/net/sf/briar/transport/ConnectionEncrypterImpl.java
+++ b/components/net/sf/briar/transport/ConnectionEncrypterImpl.java
@@ -18,25 +18,21 @@ import javax.crypto.spec.IvParameterSpec;
 class ConnectionEncrypterImpl extends FilterOutputStream
 implements ConnectionEncrypter {
 
-	private final int transportId;
-	private final long connection;
 	private final Cipher ivCipher, frameCipher;
 	private final SecretKey frameKey;
 	private final byte[] iv;
 
 	private long frame = 0L;
-	private boolean started = false, betweenFrames = false;
+	private boolean ivWritten = false, betweenFrames = false;
 
-	ConnectionEncrypterImpl(OutputStream out, int transportId,
-			long connection, Cipher ivCipher, Cipher frameCipher,
-			SecretKey ivKey, SecretKey frameKey) {
+	ConnectionEncrypterImpl(OutputStream out, boolean initiator,
+			int transportId, long connection, Cipher ivCipher,
+			Cipher frameCipher, SecretKey ivKey, SecretKey frameKey) {
 		super(out);
-		this.transportId = transportId;
-		this.connection = connection;
 		this.ivCipher = ivCipher;
 		this.frameCipher = frameCipher;
 		this.frameKey = frameKey;
-		iv = new byte[IV_LENGTH];
+		iv = IvEncoder.encodeIv(initiator, transportId, connection);
 		try {
 			ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
 		} catch(InvalidKeyException badKey) {
@@ -51,7 +47,7 @@ implements ConnectionEncrypter {
 	}
 
 	public void writeMac(byte[] mac) throws IOException {
-		if(!started || betweenFrames) throw new IllegalStateException();
+		if(!ivWritten || betweenFrames) throw new IllegalStateException();
 		try {
 			out.write(frameCipher.doFinal(mac));
 		} catch(BadPaddingException badCipher) {
@@ -64,7 +60,7 @@ implements ConnectionEncrypter {
 
 	@Override
 	public void write(int b) throws IOException {
-		if(!started) writeIv();
+		if(!ivWritten) writeIv();
 		if(betweenFrames) initialiseCipher();
 		byte[] ciphertext = frameCipher.update(new byte[] {(byte) b});
 		if(ciphertext != null) out.write(ciphertext);
@@ -77,16 +73,15 @@ implements ConnectionEncrypter {
 
 	@Override
 	public void write(byte[] b, int off, int len) throws IOException {
-		if(!started) writeIv();
+		if(!ivWritten) writeIv();
 		if(betweenFrames) initialiseCipher();
 		byte[] ciphertext = frameCipher.update(b, off, len);
 		if(ciphertext != null) out.write(ciphertext);
 	}
 
 	private void writeIv() throws IOException {
-		assert !started;
+		assert !ivWritten;
 		assert !betweenFrames;
-		IvEncoder.encodeIv(iv, transportId, connection, 0L);
 		try {
 			out.write(ivCipher.doFinal(iv));
 		} catch(BadPaddingException badCipher) {
@@ -94,15 +89,15 @@ implements ConnectionEncrypter {
 		} catch(IllegalBlockSizeException badCipher) {
 			throw new RuntimeException(badCipher);
 		}
-		started = true;
+		ivWritten = true;
 		betweenFrames = true;
 	}
 
 	private void initialiseCipher() {
-		assert started;
+		assert ivWritten;
 		assert betweenFrames;
 		if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
-		IvEncoder.encodeIv(iv, transportId, connection, frame);
+		IvEncoder.updateIv(iv, frame);
 		IvParameterSpec ivSpec = new IvParameterSpec(iv);
 		try {
 			frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
diff --git a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
index 016e4fb43b..7629e02562 100644
--- a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
@@ -23,7 +23,8 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
 	}
 
 	public ConnectionReader createConnectionReader(InputStream in,
-			int transportId, long connection, byte[] secret) {
+			boolean initiator, int transportId, long connection,
+			byte[] secret) {
 		SecretKey macKey = crypto.deriveIncomingMacKey(secret);
 		SecretKey frameKey = crypto.deriveIncomingFrameKey(secret);
 		Cipher frameCipher = crypto.getFrameCipher();
@@ -34,7 +35,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
 			throw new IllegalArgumentException(e);
 		}
 		ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in,
-				transportId, connection, frameCipher, frameKey);
+				initiator, transportId, connection, frameCipher, frameKey);
 		return new ConnectionReaderImpl(decrypter, mac);
 	}
 }
diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
index 7915ecf718..12664ef7af 100644
--- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
+++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
@@ -81,7 +81,7 @@ DatabaseListener {
 	}
 
 	private synchronized byte[] encryptIv(ContactId c, long connection) {
-		byte[] iv = IvEncoder.encodeIv(transportId, connection);
+		byte[] iv = IvEncoder.encodeIv(true, transportId, connection);
 		Cipher cipher = contactToCipher.get(c);
 		assert cipher != null;
 		try {
diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
index 9d0768c03c..42ed959005 100644
--- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
@@ -23,7 +23,8 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 	}
 
 	public ConnectionWriter createConnectionWriter(OutputStream out,
-			int transportId, long connection, byte[] secret) {
+			boolean initiator, int transportId, long connection,
+			byte[] secret) {
 		SecretKey macKey = crypto.deriveOutgoingMacKey(secret);
 		SecretKey ivKey = crypto.deriveOutgoingIvKey(secret);
 		SecretKey frameKey = crypto.deriveOutgoingFrameKey(secret);
@@ -36,8 +37,8 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 			throw new IllegalArgumentException(badKey);
 		}
 		ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
-				transportId, connection, ivCipher, frameCipher, ivKey,
-				frameKey);
+				initiator, transportId, connection, ivCipher, frameCipher,
+				ivKey, frameKey);
 		return new ConnectionWriterImpl(encrypter, mac);
 	}
 }
diff --git a/components/net/sf/briar/transport/IvEncoder.java b/components/net/sf/briar/transport/IvEncoder.java
index 481f0304a5..6744b04495 100644
--- a/components/net/sf/briar/transport/IvEncoder.java
+++ b/components/net/sf/briar/transport/IvEncoder.java
@@ -5,8 +5,11 @@ import net.sf.briar.util.ByteUtils;
 
 class IvEncoder {
 
-	static byte[] encodeIv(int transportId, long connection) {
+	static byte[] encodeIv(boolean initiator, int transportId,
+			long connection) {
 		byte[] iv = new byte[IV_LENGTH];
+		// Bit 31 is the initiator flag
+		if(initiator) iv[3] = 1;
 		// Encode the transport identifier as an unsigned 16-bit integer
 		ByteUtils.writeUint16(transportId, iv, 4);
 		// Encode the connection number as an unsigned 32-bit integer
@@ -14,20 +17,9 @@ class IvEncoder {
 		return iv;
 	}
 
-	static void encodeIv(byte[] iv, int transportId, long connection,
-			long frame) {
+	static void updateIv(byte[] iv, long frame) {
 		if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
-		// The first 16 bits of the IV must be zero (reserved)
-		iv[0] = 0;
-		iv[1] = 0;
-		// Encode the transport identifier as an unsigned 16-bit integer
-		ByteUtils.writeUint16(transportId, iv, 4);
-		// Encode the connection number as an unsigned 32-bit integer
-		ByteUtils.writeUint32(connection, iv, 6);
 		// Encode the frame number as an unsigned 32-bit integer
 		ByteUtils.writeUint32(frame, iv, 10);
-		// The last 16 bits of the IV must be zero (block number)
-		iv[14] = 0;
-		iv[15] = 0;
 	}
 }
diff --git a/test/net/sf/briar/FileReadWriteTest.java b/test/net/sf/briar/FileReadWriteTest.java
index 5c0ca77c2f..fa54fd4a3a 100644
--- a/test/net/sf/briar/FileReadWriteTest.java
+++ b/test/net/sf/briar/FileReadWriteTest.java
@@ -135,7 +135,7 @@ public class FileReadWriteTest extends TestCase {
 		OutputStream out = new FileOutputStream(file);
 		// Use Alice's secret for writing
 		ConnectionWriter w = connectionWriterFactory.createConnectionWriter(out,
-				transportId, connection, aliceSecret);
+				true, transportId, connection, aliceSecret);
 		out = w.getOutputStream();
 
 		AckWriter a = protocolWriterFactory.createAckWriter(out);
@@ -194,7 +194,7 @@ public class FileReadWriteTest extends TestCase {
 		assertEquals(16, offset);
 		// Use Bob's secret for reading
 		ConnectionReader r = connectionReaderFactory.createConnectionReader(in,
-				transportId, connection, bobSecret);
+				true, transportId, connection, bobSecret);
 		in = r.getInputStream();
 		ProtocolReader protocolReader =
 			protocolReaderFactory.createProtocolReader(in);
diff --git a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
index 1787033468..f785d68122 100644
--- a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
@@ -1,7 +1,5 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
-
 import java.io.ByteArrayInputStream;
 import java.util.Arrays;
 
@@ -43,25 +41,33 @@ public class ConnectionDecrypterImplTest extends TestCase {
 		byte[] ciphertext = new byte[1 + MAC_LENGTH];
 		ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
 		// Check that one byte plus a MAC can be read
-		ConnectionDecrypter d = new ConnectionDecrypterImpl(in, transportId,
-				connection, frameCipher, frameKey);
+		ConnectionDecrypter d = new ConnectionDecrypterImpl(in, true,
+				transportId, connection, frameCipher, frameKey);
 		assertFalse(d.getInputStream().read() == -1);
 		d.readMac(new byte[MAC_LENGTH]);
 		assertTrue(d.getInputStream().read() == -1);
 	}
 
 	@Test
-	public void testDecryption() throws Exception {
+	public void testInitiatorDecryption() throws Exception {
+		testDecryption(true);
+	}
+
+	@Test
+	public void testResponderDecryption() throws Exception {
+		testDecryption(false);
+	}
+
+	private void testDecryption(boolean initiator) throws Exception {
 		// Calculate the expected plaintext for the first frame
 		byte[] ciphertext = new byte[123];
-		byte[] iv = new byte[IV_LENGTH];
-		IvEncoder.encodeIv(iv, transportId, connection, 0L);
+		byte[] iv = IvEncoder.encodeIv(initiator, transportId, connection);
 		IvParameterSpec ivSpec = new IvParameterSpec(iv);
 		frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec);
 		byte[] plaintext = frameCipher.doFinal(ciphertext);
 		// Calculate the expected plaintext for the second frame
 		byte[] ciphertext1 = new byte[1234];
-		IvEncoder.encodeIv(iv, transportId, connection, 1L);
+		IvEncoder.updateIv(iv, 1L);
 		ivSpec = new IvParameterSpec(iv);
 		frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec);
 		byte[] plaintext1 = frameCipher.doFinal(ciphertext1);
@@ -72,8 +78,8 @@ public class ConnectionDecrypterImplTest extends TestCase {
 		out.write(ciphertext1);
 		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
 		// Use a ConnectionDecrypter to decrypt the ciphertext
-		ConnectionDecrypter d = new ConnectionDecrypterImpl(in, transportId,
-				connection, frameCipher, frameKey);
+		ConnectionDecrypter d = new ConnectionDecrypterImpl(in, initiator,
+				transportId, connection, frameCipher, frameKey);
 		// First frame
 		byte[] decrypted = new byte[plaintext.length - MAC_LENGTH];
 		TestUtils.readFully(d.getInputStream(), decrypted);
diff --git a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
index 59624159dd..9121b6b381 100644
--- a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
@@ -40,17 +40,27 @@ public class ConnectionEncrypterImplTest extends TestCase {
 	@Test
 	public void testSingleByteFrame() throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		ConnectionEncrypter e = new ConnectionEncrypterImpl(out, transportId,
-				connection, ivCipher, frameCipher, ivKey, frameKey);
+		ConnectionEncrypter e = new ConnectionEncrypterImpl(out, true,
+				transportId, connection, ivCipher, frameCipher, ivKey,
+				frameKey);
 		e.getOutputStream().write((byte) 0);
 		e.writeMac(new byte[MAC_LENGTH]);
 		assertEquals(IV_LENGTH + 1 + MAC_LENGTH, out.toByteArray().length);
 	}
 
 	@Test
-	public void testEncryption() throws Exception {
+	public void testInitiatorEncryption() throws Exception {
+		testEncryption(true);
+	}
+
+	@Test
+	public void testResponderEncryption() throws Exception {
+		testEncryption(false);
+	}
+
+	private void testEncryption(boolean initiator) throws Exception {
 		// Calculate the expected ciphertext for the IV
-		byte[] iv = IvEncoder.encodeIv(transportId, connection);
+		byte[] iv = IvEncoder.encodeIv(initiator, transportId, connection);
 		assertEquals(IV_LENGTH, iv.length);
 		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
 		byte[] encryptedIv = ivCipher.doFinal(iv);
@@ -58,7 +68,6 @@ public class ConnectionEncrypterImplTest extends TestCase {
 		// Calculate the expected ciphertext for the first frame
 		byte[] plaintext = new byte[123];
 		byte[] plaintextMac = new byte[MAC_LENGTH];
-		IvEncoder.encodeIv(iv, transportId, connection, 0L);
 		IvParameterSpec ivSpec = new IvParameterSpec(iv);
 		frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
 		byte[] ciphertext = new byte[plaintext.length + plaintextMac.length];
@@ -68,7 +77,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
 				offset);
 		// Calculate the expected ciphertext for the second frame
 		byte[] plaintext1 = new byte[1234];
-		IvEncoder.encodeIv(iv, transportId, connection, 1L);
+		IvEncoder.updateIv(iv, 1L);
 		ivSpec = new IvParameterSpec(iv);
 		frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
 		byte[] ciphertext1 = new byte[plaintext1.length + plaintextMac.length];
@@ -84,8 +93,9 @@ public class ConnectionEncrypterImplTest extends TestCase {
 		byte[] expected = out.toByteArray();
 		// Use a ConnectionEncrypter to encrypt the plaintext
 		out.reset();
-		ConnectionEncrypter e = new ConnectionEncrypterImpl(out, transportId,
-				connection, ivCipher, frameCipher, ivKey, frameKey);
+		ConnectionEncrypter e = new ConnectionEncrypterImpl(out, initiator,
+				transportId, connection, ivCipher, frameCipher, ivKey,
+				frameKey);
 		e.getOutputStream().write(plaintext);
 		e.writeMac(plaintextMac);
 		e.getOutputStream().write(plaintext1);
diff --git a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
index 4d8af92f52..de66b5438a 100644
--- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
@@ -65,7 +65,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
 		Cipher ivCipher = crypto.getIvCipher();
 		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
-		byte[] iv = IvEncoder.encodeIv(transportId, 3L);
+		byte[] iv = IvEncoder.encodeIv(true, transportId, 3L);
 		byte[] encryptedIv = ivCipher.doFinal(iv);
 
 		Mockery context = new Mockery();
diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java
index d7c98f09a7..f676f838cc 100644
--- a/test/net/sf/briar/transport/FrameReadWriteTest.java
+++ b/test/net/sf/briar/transport/FrameReadWriteTest.java
@@ -50,9 +50,18 @@ public class FrameReadWriteTest extends TestCase {
 	}
 
 	@Test
-	public void testWriteAndRead() throws Exception {
+	public void testInitiatorWriteAndRead() throws Exception {
+		testWriteAndRead(true);
+	}
+
+	@Test
+	public void testResponderWriteAndRead() throws Exception {
+		testWriteAndRead(false);
+	}
+
+	private void testWriteAndRead(boolean initiator) throws Exception {
 		// Calculate the expected ciphertext for the IV
-		byte[] iv = IvEncoder.encodeIv(transportId, connection);
+		byte[] iv = IvEncoder.encodeIv(initiator, transportId, connection);
 		assertEquals(IV_LENGTH, iv.length);
 		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
 		byte[] encryptedIv = ivCipher.doFinal(iv);
@@ -65,8 +74,8 @@ public class FrameReadWriteTest extends TestCase {
 		// Write the frames
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
-				transportId, connection, ivCipher, frameCipher, ivKey,
-				frameKey);
+				initiator, transportId, connection, ivCipher, frameCipher,
+				ivKey, frameKey);
 		mac.init(macKey);
 		ConnectionWriter writer = new ConnectionWriterImpl(encrypter, mac);
 		OutputStream out1 = writer.getOutputStream();
@@ -80,7 +89,7 @@ public class FrameReadWriteTest extends TestCase {
 		assertEquals(IV_LENGTH, in.read(recoveredIv));
 		assertTrue(Arrays.equals(encryptedIv, recoveredIv));
 		ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in,
-				transportId, connection, frameCipher, frameKey);
+				initiator, transportId, connection, frameCipher, frameKey);
 		ConnectionReader reader = new ConnectionReaderImpl(decrypter, mac);
 		InputStream in1 = reader.getInputStream();
 		byte[] recovered = new byte[frame.length];
-- 
GitLab