diff --git a/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java
index 5626b2ba04eb9bda6531321948a45f867c183168..0de25f31f9f4542b8c9a5c2a9278ff804b38ef17 100644
--- a/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTest.java
@@ -2,10 +2,13 @@ package org.briarproject;
 
 import net.jodah.concurrentunit.Waiter;
 
+import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.KeyPair;
 import org.briarproject.api.crypto.SecretKey;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfEntry;
@@ -23,6 +26,7 @@ import org.briarproject.api.event.MessageStateChangedEvent;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.identity.LocalAuthor;
+import org.briarproject.api.introduction.IntroducerProtocolState;
 import org.briarproject.api.introduction.IntroductionManager;
 import org.briarproject.api.introduction.IntroductionMessage;
 import org.briarproject.api.introduction.IntroductionRequest;
@@ -66,12 +70,23 @@ import javax.inject.Inject;
 import static org.briarproject.TestPluginsModule.MAX_LATENCY;
 import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
 import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
+import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
+import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
+import static org.briarproject.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.api.introduction.IntroductionConstants.MAC_LENGTH;
 import static org.briarproject.api.introduction.IntroductionConstants.NAME;
 import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
+import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
+import static org.briarproject.api.introduction.IntroductionConstants.STATE;
+import static org.briarproject.api.introduction.IntroductionConstants.TIME;
+import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
 import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
+import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
 import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
+import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
 import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
 import static org.briarproject.api.sync.ValidationManager.State.INVALID;
 import static org.junit.Assert.assertEquals;
@@ -90,6 +105,8 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	@Inject
 	Clock clock;
 	@Inject
+	CryptoComponent crypto;
+	@Inject
 	AuthorFactory authorFactory;
 
 	// objects accessed from background threads need to be volatile
@@ -154,32 +171,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroductionSession() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			contactId2 = contactManager0.addContact(author2,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0,
-					author1.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -259,29 +257,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroductionSessionFirstDecline() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			contactId2 = contactManager0.addContact(author2, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -352,29 +334,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroductionSessionSecondDecline() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			contactId2 = contactManager0.addContact(author2, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), false, true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), false,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -440,29 +406,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroductionSessionDelayedFirstDecline() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			contactId2 = contactManager0.addContact(author2, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), false, true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), false,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -519,21 +469,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroductionToSameContact() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducee as contact
-			contactId1 = contactManager0.addContact(author1, author0.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0, author1.getId(),
-					master, clock.currentTimeMillis(), true, true, true
-			);
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -669,32 +611,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testSessionIdReuse() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			contactId2 = contactManager0.addContact(author2,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0,
-					author1.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -766,32 +689,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroducerRemovedCleanup() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			contactId2 = contactManager0.addContact(author2,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0,
-					author1.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -852,32 +756,13 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	public void testIntroduceesRemovedCleanup() throws Exception {
 		startLifecycles();
 		try {
-			// Add Identities
+			// Add Identities And Contacts
 			addDefaultIdentities();
+			addDefaultContacts();
 
 			// Add Transport Properties
 			addTransportProperties();
 
-			// Add introducees as contacts
-			contactId1 = contactManager0.addContact(author1,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			contactId2 = contactManager0.addContact(author2,
-					author0.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			// Add introducer back
-			contactId0 = contactManager1.addContact(author0,
-					author1.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			ContactId contactId02 = contactManager2.addContact(author0,
-					author2.getId(), master, clock.currentTimeMillis(), true,
-					true, true
-			);
-			assertTrue(contactId0.equals(contactId02));
-
 			// listen to events
 			IntroducerListener listener0 = new IntroducerListener();
 			t0.getEventBus().addListener(listener0);
@@ -948,7 +833,149 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 		}
 	}
 
-	// TODO add a test for faking responses when #256 is implemented
+	@Test
+	public void testFakeResponse() throws Exception {
+		startLifecycles();
+		try {
+			addDefaultIdentities();
+			addDefaultContacts();
+			addTransportProperties();
+
+			// listen to events
+			IntroducerListener listener0 = new IntroducerListener();
+			t0.getEventBus().addListener(listener0);
+			IntroduceeListener listener1 = new IntroduceeListener(1, true);
+			t1.getEventBus().addListener(listener1);
+			IntroduceeListener listener2 = new IntroduceeListener(2, true);
+			t2.getEventBus().addListener(listener2);
+
+			// make introduction
+			long time = clock.currentTimeMillis();
+			Contact introducee1 = contactManager0.getContact(contactId1);
+			Contact introducee2 = contactManager0.getContact(contactId2);
+			introductionManager0
+					.makeIntroduction(introducee1, introducee2, "Hi!", time);
+
+			// sync first request message
+			deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
+			eventWaiter.await(TIMEOUT, 1);
+			assertTrue(listener1.requestReceived);
+
+			// sync first response
+			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
+			eventWaiter.await(TIMEOUT, 1);
+			assertTrue(listener0.response1Received);
+
+			// get SessionId
+			List<IntroductionMessage> list = new ArrayList<>(
+					introductionManager1.getIntroductionMessages(contactId0));
+			assertEquals(2, list.size());
+			assertTrue(list.get(0) instanceof IntroductionRequest);
+			IntroductionRequest msg = (IntroductionRequest) list.get(0);
+			SessionId sessionId = msg.getSessionId();
+
+			// get contact group
+			IntroductionGroupFactory groupFactory =
+					t0.getIntroductionGroupFactory();
+			Group group = groupFactory.createIntroductionGroup(introducee1);
+
+			// get data for contact2
+			long timestamp = clock.currentTimeMillis();
+			KeyPair eKeyPair = crypto.generateAgreementKeyPair();
+			byte[] ePublicKey = eKeyPair.getPublic().getEncoded();
+			TransportProperties tp = new TransportProperties(
+					Collections.singletonMap("key", "value"));
+			BdfDictionary tpDict = BdfDictionary.of(new BdfEntry("fake", tp));
+
+			// create a fake response
+			BdfDictionary d = BdfDictionary.of(
+					new BdfEntry(TYPE, TYPE_RESPONSE),
+					new BdfEntry(SESSION_ID, sessionId),
+					new BdfEntry(GROUP_ID, group.getId()),
+					new BdfEntry(ACCEPT, true),
+					new BdfEntry(TIME, timestamp),
+					new BdfEntry(E_PUBLIC_KEY, ePublicKey),
+					new BdfEntry(TRANSPORT, tpDict)
+			);
+
+			// add the message to the queue
+			DatabaseComponent db0 = t0.getDatabaseComponent();
+			MessageSender sender0 = t0.getMessageSender();
+			Transaction txn = db0.startTransaction(false);
+			try {
+				sender0.sendMessage(txn, d);
+				txn.setComplete();
+			} finally {
+				db0.endTransaction(txn);
+			}
+
+			// send the fake response
+			deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
+
+			// fake session state for introducer, so she doesn't abort
+			ClientHelper clientHelper0 = t0.getClientHelper();
+			BdfDictionary state =
+					clientHelper0.getMessageMetadataAsDictionary(sessionId);
+			state.put(STATE, IntroducerProtocolState.AWAIT_ACKS.getValue());
+			clientHelper0.mergeMessageMetadata(sessionId, state);
+
+			// sync back the ACK
+			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
+
+			// create a fake ACK
+			// TODO do we need to actually calculate a MAC and signature here?
+			byte[] mac = TestUtils.getRandomBytes(MAC_LENGTH);
+			byte[] sig = TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
+			d = BdfDictionary.of(
+					new BdfEntry(TYPE, TYPE_ACK),
+					new BdfEntry(SESSION_ID, sessionId),
+					new BdfEntry(GROUP_ID, group.getId()),
+					new BdfEntry(MAC, mac),
+					new BdfEntry(SIGNATURE, sig)
+			);
+
+			// add the fake ACK to the message queue
+			txn = db0.startTransaction(false);
+			try {
+				sender0.sendMessage(txn, d);
+				txn.setComplete();
+			} finally {
+				db0.endTransaction(txn);
+			}
+
+			// make sure the contact was already added (as inactive)
+			DatabaseComponent db1 = t1.getDatabaseComponent();
+			txn = db1.startTransaction(true);
+			try {
+				assertEquals(2, db1.getContacts(txn).size());
+				txn.setComplete();
+			} finally {
+				db1.endTransaction(txn);
+			}
+
+			// send the fake ACK
+			deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
+
+			// make sure session was aborted and contact deleted again
+			txn = db1.startTransaction(true);
+			try {
+				assertEquals(1, db1.getContacts(txn).size());
+				txn.setComplete();
+			} finally {
+				db1.endTransaction(txn);
+			}
+
+			// there should now be an abort message to sync back
+			deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
+
+			// ensure introducer got the abort
+			state = clientHelper0.getMessageMetadataAsDictionary(sessionId);
+			assertEquals(IntroducerProtocolState.ERROR.getValue(),
+					state.getLong(STATE).intValue());
+		} finally {
+			stopLifecycles();
+		}
+	}
 
 	@After
 	public void tearDown() throws InterruptedException {
@@ -991,20 +1018,48 @@ public class IntroductionIntegrationTest extends BriarTestCase {
 	}
 
 	private void addDefaultIdentities() throws DbException {
-		author0 = authorFactory.createLocalAuthor(INTRODUCER,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
+		KeyPair keyPair0 = crypto.generateSignatureKeyPair();
+		byte[] publicKey0 = keyPair0.getPublic().getEncoded();
+		byte[] privateKey0 = keyPair0.getPrivate().getEncoded();
+		author0 = authorFactory
+				.createLocalAuthor(INTRODUCER, publicKey0, privateKey0);
 		identityManager0.addLocalAuthor(author0);
-		author1 = authorFactory.createLocalAuthor(INTRODUCEE1,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
+		KeyPair keyPair1 = crypto.generateSignatureKeyPair();
+		byte[] publicKey1 = keyPair1.getPublic().getEncoded();
+		byte[] privateKey1 = keyPair1.getPrivate().getEncoded();
+		author1 = authorFactory
+				.createLocalAuthor(INTRODUCEE1, publicKey1, privateKey1);
 		identityManager1.addLocalAuthor(author1);
-		author2 = authorFactory.createLocalAuthor(INTRODUCEE2,
-				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
-				TestUtils.getRandomBytes(123));
+		KeyPair keyPair2 = crypto.generateSignatureKeyPair();
+		byte[] publicKey2 = keyPair2.getPublic().getEncoded();
+		byte[] privateKey2 = keyPair2.getPrivate().getEncoded();
+		author2 = authorFactory
+				.createLocalAuthor(INTRODUCEE2, publicKey2, privateKey2);
 		identityManager2.addLocalAuthor(author2);
 	}
 
+	private void addDefaultContacts() throws DbException {
+		// Add introducees as contacts
+		contactId1 = contactManager0.addContact(author1,
+				author0.getId(), master, clock.currentTimeMillis(), true,
+				true, true
+		);
+		contactId2 = contactManager0.addContact(author2,
+				author0.getId(), master, clock.currentTimeMillis(), true,
+				true, true
+		);
+		// Add introducer back
+		contactId0 = contactManager1.addContact(author0,
+				author1.getId(), master, clock.currentTimeMillis(), true,
+				true, true
+		);
+		ContactId contactId02 = contactManager2.addContact(author0,
+				author2.getId(), master, clock.currentTimeMillis(), true,
+				true, true
+		);
+		assertTrue(contactId0.equals(contactId02));
+	}
+
 	private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
 			SyncSessionFactory toSync, ContactId toId)
 			throws IOException, TimeoutException {
diff --git a/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTestComponent.java
index 733082ef0bd446a8c9ab805e6a11091de9653833..8e3e770420efdd5bdf6c6133f25926b55cd971c4 100644
--- a/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTestComponent.java
+++ b/briar-android-tests/src/test/java/org/briarproject/IntroductionIntegrationTestComponent.java
@@ -1,5 +1,6 @@
 package org.briarproject;
 
+import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.event.EventBus;
@@ -85,6 +86,8 @@ public interface IntroductionIntegrationTestComponent {
 
 	DatabaseComponent getDatabaseComponent();
 
+	ClientHelper getClientHelper();
+
 	MessageSender getMessageSender();
 
 	IntroductionGroupFactory getIntroductionGroupFactory();
diff --git a/briar-api/src/org/briarproject/api/contact/ContactManager.java b/briar-api/src/org/briarproject/api/contact/ContactManager.java
index 409d26d88f5de1cc6c1efb76e474e052093a88ba..5203da3004764c7d36909ca354a559d8e2905b7c 100644
--- a/briar-api/src/org/briarproject/api/contact/ContactManager.java
+++ b/briar-api/src/org/briarproject/api/contact/ContactManager.java
@@ -41,8 +41,12 @@ public interface ContactManager {
 	/** Removes a contact and all associated state. */
 	void removeContact(ContactId c) throws DbException;
 
+	/** Removes a contact and all associated state. */
+	void removeContact(Transaction txn, ContactId c) throws DbException;
+
 	/** Marks a contact as active or inactive. */
-	void setContactActive(ContactId c, boolean active) throws DbException;
+	void setContactActive(Transaction txn, ContactId c, boolean active)
+			throws DbException;
 
 	/** Return true if a contact with this name and public key already exists */
 	boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
index 1806f76d72b91dc9fda9d0ea71c9b72fe8d68995..50a9c94d565d612f645fc5b5f8cbba561d937f18 100644
--- a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
+++ b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
@@ -43,6 +43,12 @@ public interface CryptoComponent {
 	 */
 	SecretKey deriveHeaderKey(SecretKey master, boolean alice);
 
+	/**
+	 * Derives a message authentication code key from the given master secret.
+	 * @param alice whether the key is for use by Alice or Bob.
+	 */
+	SecretKey deriveMacKey(SecretKey master, boolean alice);
+
 	/**
 	 * Derives a nonce from the given master secret for one of the parties to
 	 * sign.
diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java b/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java
index 9e45da0e74595c4752e5748cd25314a0dd5f6e37..ac8975e5c2f7d83950dfcbf45a89353a5d615f1b 100644
--- a/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java
+++ b/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java
@@ -29,6 +29,9 @@ public interface IntroductionConstants {
 	String MAC = "mac";
 	String SIGNATURE = "signature";
 
+	/* Validation Constants */
+	int MAC_LENGTH = 32;
+
 	/* Introducer Local State Metadata */
 	String STATE = "state";
 	String ROLE = "role";
@@ -61,6 +64,11 @@ public interface IntroductionConstants {
 	String EXISTS = "contactExists";
 	String REMOTE_AUTHOR_IS_US = "remoteAuthorIsUs";
 	String ANSWERED = "answered";
+	String NONCE = "nonce";
+	String MAC_KEY = "macKey";
+	String OUR_TRANSPORT = "ourTransport";
+	String OUR_MAC = "ourMac";
+	String OUR_SIGNATURE = "ourSignature";
 
 	String TASK = "task";
 	int TASK_ADD_CONTACT = 0;
diff --git a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java b/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
index fb6ede72d4cddda86ad12e77c5402eb5fb7d0d16..44bc5979e6b8725109dede1b22783d10a1a097a1 100644
--- a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
+++ b/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
@@ -114,15 +114,9 @@ class ContactManagerImpl implements ContactManager, RemoveIdentityHook {
 	}
 
 	@Override
-	public void setContactActive(ContactId c, boolean active)
+	public void setContactActive(Transaction txn, ContactId c, boolean active)
 			throws DbException {
-		Transaction txn = db.startTransaction(false);
-		try {
-			db.setContactActive(txn, c, active);
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
+		db.setContactActive(txn, c, active);
 	}
 
 	@Override
@@ -145,7 +139,8 @@ class ContactManagerImpl implements ContactManager, RemoveIdentityHook {
 		return exists;
 	}
 
-	private void removeContact(Transaction txn, ContactId c)
+	@Override
+	public void removeContact(Transaction txn, ContactId c)
 			throws DbException {
 		Contact contact = db.getContact(txn, c);
 		for (RemoveContactHook hook : removeHooks)
diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
index 169bfb7818f9d8002cbeac905dc9451584a00d7b..22698a22ff70aac5087158a3f17684aab0c87686 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
@@ -87,6 +87,9 @@ class CryptoComponentImpl implements CryptoComponent {
 	// KDF labels for header key derivation
 	private static final byte[] A_HEADER = ascii("ALICE_HEADER_KEY");
 	private static final byte[] B_HEADER = ascii("BOB_HEADER_KEY");
+	// KDF labels for MAC key derivation
+	private static final byte[] A_MAC = ascii("ALICE_MAC_KEY");
+	private static final byte[] B_MAC = ascii("BOB_MAC_KEY");
 	// KDF label for key rotation
 	private static final byte[] ROTATE = ascii("ROTATE");
 
@@ -233,6 +236,11 @@ class CryptoComponentImpl implements CryptoComponent {
 		return new SecretKey(macKdf(master, alice ? A_INVITE : B_INVITE));
 	}
 
+	@Override
+	public SecretKey deriveMacKey(SecretKey master, boolean alice) {
+		return new SecretKey(macKdf(master, alice ? A_MAC : B_MAC));
+	}
+
 	@Override
 	public byte[] deriveSignatureNonce(SecretKey master,
 			boolean alice) {
diff --git a/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java b/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
index 58cf2821c6d64996da207bc32c4a9e5081532502..8f77539c79faee46489301b2fe982740ad089fa3 100644
--- a/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
+++ b/briar-core/src/org/briarproject/introduction/IntroduceeEngine.java
@@ -46,7 +46,9 @@ import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TI
 import static org.briarproject.api.introduction.IntroductionConstants.MSG;
 import static org.briarproject.api.introduction.IntroductionConstants.NAME;
 import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
+import static org.briarproject.api.introduction.IntroductionConstants.OUR_MAC;
 import static org.briarproject.api.introduction.IntroductionConstants.OUR_PUBLIC_KEY;
+import static org.briarproject.api.introduction.IntroductionConstants.OUR_SIGNATURE;
 import static org.briarproject.api.introduction.IntroductionConstants.OUR_TIME;
 import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
@@ -192,6 +194,7 @@ public class IntroduceeEngine
 			// we already sent our ACK and now received the other one
 			else if (currentState == AWAIT_ACK) {
 				localState.put(TASK, TASK_ACTIVATE_CONTACT);
+				addAckData(localState, msg);
 				messages = Collections.emptyList();
 				events = Collections.emptyList();
 			}
@@ -241,6 +244,13 @@ public class IntroduceeEngine
 		}
 	}
 
+	private void addAckData(BdfDictionary localState, BdfDictionary msg)
+			throws FormatException {
+
+		localState.put(MAC, msg.getRaw(MAC));
+		localState.put(SIGNATURE, msg.getRaw(SIGNATURE));
+	}
+
 	private BdfDictionary getAckMessage(BdfDictionary localState)
 			throws FormatException {
 
@@ -248,8 +258,8 @@ public class IntroduceeEngine
 		m.put(TYPE, TYPE_ACK);
 		m.put(GROUP_ID, localState.getRaw(GROUP_ID));
 		m.put(SESSION_ID, localState.getRaw(SESSION_ID));
-		m.put(MAC, localState.getRaw(MAC));
-		m.put(SIGNATURE, localState.getRaw(SIGNATURE));
+		m.put(MAC, localState.getRaw(OUR_MAC));
+		m.put(SIGNATURE, localState.getRaw(OUR_SIGNATURE));
 
 		if (LOG.isLoggable(INFO)) {
 			LOG.info("Sending ACK " + " to " +
diff --git a/briar-core/src/org/briarproject/introduction/IntroduceeManager.java b/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
index 2c1db51ef900a175561459f65b1bb309f8b551dc..0223c14b3e26b8616dc8d940d0483e4c90939d06 100644
--- a/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
+++ b/briar-core/src/org/briarproject/introduction/IntroduceeManager.java
@@ -13,6 +13,7 @@ import org.briarproject.api.crypto.KeyParser;
 import org.briarproject.api.crypto.PrivateKey;
 import org.briarproject.api.crypto.PublicKey;
 import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.api.crypto.Signature;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.db.DatabaseComponent;
@@ -23,6 +24,8 @@ import org.briarproject.api.event.IntroductionSucceededEvent;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.AuthorId;
+import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.properties.TransportProperties;
 import org.briarproject.api.properties.TransportPropertyManager;
 import org.briarproject.api.sync.GroupId;
@@ -32,6 +35,7 @@ import org.briarproject.api.system.Clock;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Logger;
@@ -53,13 +57,18 @@ import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
 import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
 import static org.briarproject.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
 import static org.briarproject.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.api.introduction.IntroductionConstants.MAC_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
 import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
 import static org.briarproject.api.introduction.IntroductionConstants.NAME;
+import static org.briarproject.api.introduction.IntroductionConstants.NONCE;
 import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE;
+import static org.briarproject.api.introduction.IntroductionConstants.OUR_MAC;
 import static org.briarproject.api.introduction.IntroductionConstants.OUR_PRIVATE_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.OUR_PUBLIC_KEY;
+import static org.briarproject.api.introduction.IntroductionConstants.OUR_SIGNATURE;
 import static org.briarproject.api.introduction.IntroductionConstants.OUR_TIME;
+import static org.briarproject.api.introduction.IntroductionConstants.OUR_TRANSPORT;
 import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID;
 import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
@@ -92,6 +101,7 @@ class IntroduceeManager {
 	private final TransportPropertyManager transportPropertyManager;
 	private final AuthorFactory authorFactory;
 	private final ContactManager contactManager;
+	private final IdentityManager identityManager;
 	private final IntroductionGroupFactory introductionGroupFactory;
 
 	@Inject
@@ -100,6 +110,7 @@ class IntroduceeManager {
 			CryptoComponent cryptoComponent,
 			TransportPropertyManager transportPropertyManager,
 			AuthorFactory authorFactory, ContactManager contactManager,
+			IdentityManager identityManager,
 			IntroductionGroupFactory introductionGroupFactory) {
 
 		this.messageSender = messageSender;
@@ -110,6 +121,7 @@ class IntroduceeManager {
 		this.transportPropertyManager = transportPropertyManager;
 		this.authorFactory = authorFactory;
 		this.contactManager = contactManager;
+		this.identityManager = identityManager;
 		this.introductionGroupFactory = introductionGroupFactory;
 	}
 
@@ -189,18 +201,19 @@ class IntroduceeManager {
 		byte[] privateKey = keyPair.getPrivate().getEncoded();
 		Map<TransportId, TransportProperties> transportProperties =
 				transportPropertyManager.getLocalProperties(txn);
+		BdfDictionary tp = encodeTransportProperties(transportProperties);
 
 		// update session state for later
 		state.put(ACCEPT, true);
 		state.put(OUR_TIME, now);
 		state.put(OUR_PUBLIC_KEY, publicKey);
 		state.put(OUR_PRIVATE_KEY, privateKey);
+		state.put(OUR_TRANSPORT, tp);
 
 		// define action
 		BdfDictionary localAction = new BdfDictionary();
 		localAction.put(TYPE, TYPE_RESPONSE);
-		localAction.put(TRANSPORT,
-				encodeTransportProperties(transportProperties));
+		localAction.put(TRANSPORT, tp);
 		localAction.put(MESSAGE_TIME, timestamp);
 
 		// start engine and process its state update
@@ -311,24 +324,59 @@ class IntroduceeManager {
 				secretKey = cryptoComponent
 						.deriveMasterSecret(theirEphemeralKey, keyPair, alice);
 			} catch (GeneralSecurityException e) {
-				if (LOG.isLoggable(WARNING))
-					LOG.log(WARNING, e.toString(), e);
 				// we can not continue without the shared secret
-				throw new FormatException();
+				throw new DbException(e);
 			}
 
-			// TODO MAC and signature
-			localState.put(MAC, new byte[42]);
-			localState.put(SIGNATURE, new byte[42]);
+			// Derive two nonces and a MAC key from the secret master key
+			byte[] ourNonce =
+					cryptoComponent.deriveSignatureNonce(secretKey, alice);
+			byte[] theirNonce =
+					cryptoComponent.deriveSignatureNonce(secretKey, !alice);
+			SecretKey macKey = cryptoComponent.deriveMacKey(secretKey, alice);
+			SecretKey theirMacKey =
+					cryptoComponent.deriveMacKey(secretKey, !alice);
+
+			// Save the other nonce and MAC key for the verification
+			localState.put(NONCE, theirNonce);
+			localState.put(MAC_KEY, theirMacKey.getBytes());
+
+			// Sign our nonce with our long-term identity public key
+			AuthorId localAuthorId =
+					new AuthorId(localState.getRaw(LOCAL_AUTHOR_ID));
+			LocalAuthor author =
+					identityManager.getLocalAuthor(txn, localAuthorId);
+			Signature signature = cryptoComponent.getSignature();
+			KeyParser sigParser = cryptoComponent.getSignatureKeyParser();
+			try {
+				PrivateKey privKey =
+						sigParser.parsePrivateKey(author.getPrivateKey());
+				signature.initSign(privKey);
+			} catch (GeneralSecurityException e) {
+				// we can not continue without the signature
+				throw new DbException(e);
+			}
+			signature.update(ourNonce);
+			byte[] sig = signature.sign();
 
 			// The agreed timestamp is the minimum of the peers' timestamps
 			long ourTime = localState.getLong(OUR_TIME);
 			long theirTime = localState.getLong(TIME);
 			long timestamp = Math.min(ourTime, theirTime);
 
-			// Add the contact to the database
-			AuthorId localAuthorId =
-					new AuthorId(localState.getRaw(LOCAL_AUTHOR_ID));
+			// Calculate a MAC over identity public key, ephemeral public key,
+			// transport properties and timestamp.
+			BdfDictionary tp = localState.getDictionary(OUR_TRANSPORT);
+			BdfList toSignList = BdfList.of(author.getPublicKey(),
+					publicKeyBytes, tp, ourTime);
+			byte[] toSign = clientHelper.toByteArray(toSignList);
+			byte[] mac = cryptoComponent.mac(macKey, toSign);
+
+			// Add MAC and signature to localState, so it can be included in ACK
+			localState.put(OUR_MAC, mac);
+			localState.put(OUR_SIGNATURE, sig);
+
+			// Add the contact to the database as inactive
 			Author remoteAuthor = authorFactory
 					.createAuthor(localState.getString(NAME),
 							localState.getRaw(PUBLIC_KEY));
@@ -365,13 +413,57 @@ class IntroduceeManager {
 			if (!localState.getBoolean(EXISTS) &&
 					localState.containsKey(ADDED_CONTACT_ID)) {
 
+				LOG.info("Verifying Signature...");
+
+				byte[] nonce = localState.getRaw(NONCE);
+				byte[] sig = localState.getRaw(SIGNATURE);
+				byte[] keyBytes = localState.getRaw(PUBLIC_KEY);
+				try {
+					// Parse the public key
+					KeyParser keyParser = cryptoComponent.getSignatureKeyParser();
+					PublicKey key = keyParser.parsePublicKey(keyBytes);
+					// Verify the signature
+					Signature signature = cryptoComponent.getSignature();
+					signature.initVerify(key);
+					signature.update(nonce);
+					if (!signature.verify(sig)) {
+						LOG.warning("Invalid nonce signature in ACK");
+						throw new GeneralSecurityException();
+					}
+				} catch (GeneralSecurityException e) {
+					if (LOG.isLoggable(WARNING))
+						LOG.log(WARNING, e.toString(), e);
+					// we can not continue without verifying the signature
+					throw new DbException(e);
+				}
+
+				LOG.info("Verifying MAC...");
+
+				// get MAC and MAC key from session state
+				byte[] mac = localState.getRaw(MAC);
+				byte[] macKeyBytes = localState.getRaw(MAC_KEY);
+				SecretKey macKey = new SecretKey(macKeyBytes);
+
+				// get MAC data and calculate a new MAC with stored key
+				byte[] pubKey = localState.getRaw(PUBLIC_KEY);
+				byte[] ePubKey = localState.getRaw(E_PUBLIC_KEY);
+				BdfDictionary tp = localState.getDictionary(TRANSPORT);
+				long timestamp = localState.getLong(TIME);
+				BdfList toSignList = BdfList.of(pubKey, ePubKey, tp, timestamp);
+				byte[] toSign = clientHelper.toByteArray(toSignList);
+				byte[] calculatedMac = cryptoComponent.mac(macKey, toSign);
+				if (!Arrays.equals(mac, calculatedMac)) {
+					LOG.warning("Received ACK with invalid MAC");
+					throw new DbException();
+				}
+
 				LOG.info("Activating Contact...");
 
 				ContactId contactId = new ContactId(
 						localState.getLong(ADDED_CONTACT_ID).intValue());
 
 				// activate and show contact in contact list
-				db.setContactActive(txn, contactId, true);
+				contactManager.setContactActive(txn, contactId, true);
 
 				// broadcast event informing of successful introduction
 				Contact contact = db.getContact(txn, contactId);
@@ -389,7 +481,7 @@ class IntroduceeManager {
 				LOG.info("Deleting added contact due to abort...");
 				ContactId contactId = new ContactId(
 						localState.getLong(ADDED_CONTACT_ID).intValue());
-				contactManager.removeContact(contactId);
+				contactManager.removeContact(txn, contactId);
 			}
 		}
 
diff --git a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
index bf35d08f760e3a63ce57b7096c0ec1f3337e55cb..3473ad61364779980c9868840ab3f9ad00f2c997 100644
--- a/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
+++ b/briar-core/src/org/briarproject/introduction/IntroductionValidator.java
@@ -20,6 +20,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
 import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
 import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
 import static org.briarproject.api.introduction.IntroductionConstants.MAC;
+import static org.briarproject.api.introduction.IntroductionConstants.MAC_LENGTH;
 import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
 import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
 import static org.briarproject.api.introduction.IntroductionConstants.MSG;
@@ -157,7 +158,7 @@ class IntroductionValidator extends BdfMessageValidator {
 		checkSize(message, 4);
 
 		byte[] mac = message.getRaw(2);
-		// TODO length check?
+		checkLength(mac, 1, MAC_LENGTH);
 
 		byte[] sig = message.getRaw(3);
 		checkLength(sig, 1, MAX_SIGNATURE_LENGTH);
diff --git a/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java b/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
index 8b7e1afe340f2fb98087213712809f5762172505..0a91bd6864a355e54feb799be4cf897bd45f83d6 100644
--- a/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
+++ b/briar-tests/src/org/briarproject/introduction/IntroduceeManagerTest.java
@@ -5,6 +5,7 @@ import org.briarproject.TestUtils;
 import org.briarproject.api.Bytes;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
@@ -18,8 +19,8 @@ import org.briarproject.api.db.Transaction;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.AuthorId;
+import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.introduction.IntroduceeProtocolState;
-import org.briarproject.api.clients.SessionId;
 import org.briarproject.api.properties.TransportPropertyManager;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
@@ -63,34 +64,33 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
 import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST;
 import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
 import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
 public class IntroduceeManagerTest extends BriarTestCase {
 
-	final Mockery context;
-	final IntroduceeManager introduceeManager;
-	final DatabaseComponent db;
-	final CryptoComponent cryptoComponent;
-	final ClientHelper clientHelper;
-	final IntroductionGroupFactory introductionGroupFactory;
-	final MessageSender messageSender;
-	final TransportPropertyManager transportPropertyManager;
-	final AuthorFactory authorFactory;
-	final ContactManager contactManager;
-	final Clock clock;
-	final Contact introducer;
-	final Contact introducee1;
-	final Contact introducee2;
-	final Group localGroup1;
-	final Group introductionGroup1;
-	final Group introductionGroup2;
-	final Transaction txn;
-	final long time = 42L;
-	final Message localStateMessage;
-	final ClientId clientId;
-	final SessionId sessionId;
-	final Message message1;
+	private final Mockery context;
+	private final IntroduceeManager introduceeManager;
+	private final DatabaseComponent db;
+	private final CryptoComponent cryptoComponent;
+	private final ClientHelper clientHelper;
+	private final IntroductionGroupFactory introductionGroupFactory;
+	private final MessageSender messageSender;
+	private final TransportPropertyManager transportPropertyManager;
+	private final AuthorFactory authorFactory;
+	private final ContactManager contactManager;
+	private final IdentityManager identityManager;
+	private final Clock clock;
+	private final Contact introducer;
+	private final Contact introducee1;
+	private final Contact introducee2;
+	private final Group localGroup1;
+	private final Group introductionGroup1;
+	private final Transaction txn;
+	private final long time = 42L;
+	private final Message localStateMessage;
+	private final ClientId clientId;
+	private final SessionId sessionId;
+	private final Message message1;
 
 	public IntroduceeManagerTest() {
 		context = new Mockery();
@@ -105,10 +105,12 @@ public class IntroduceeManagerTest extends BriarTestCase {
 		transportPropertyManager = context.mock(TransportPropertyManager.class);
 		authorFactory = context.mock(AuthorFactory.class);
 		contactManager = context.mock(ContactManager.class);
+		identityManager = context.mock(IdentityManager.class);
 
 		introduceeManager = new IntroduceeManager(messageSender, db,
 				clientHelper, clock, cryptoComponent, transportPropertyManager,
-				authorFactory, contactManager, introductionGroupFactory);
+				authorFactory, contactManager, identityManager,
+				introductionGroupFactory);
 
 		AuthorId authorId0 = new AuthorId(TestUtils.getRandomId());
 		Author author0 = new Author(authorId0, "Introducer",
@@ -138,8 +140,6 @@ public class IntroduceeManagerTest extends BriarTestCase {
 				clientId, new byte[0]);
 		introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
 				clientId, new byte[0]);
-		introductionGroup2 = new Group(new GroupId(TestUtils.getRandomId()),
-				clientId, new byte[0]);
 
 		sessionId = new SessionId(TestUtils.getRandomId());
 		localStateMessage = new Message(