diff --git a/briar-core/src/org/briarproject/invitation/AliceConnector.java b/briar-core/src/org/briarproject/invitation/AliceConnector.java
index f641af40a65124ff9df9ae4584910aa95fd1f52e..e166398cc47af693512657fdb554b2cf7c59cbdd 100644
--- a/briar-core/src/org/briarproject/invitation/AliceConnector.java
+++ b/briar-core/src/org/briarproject/invitation/AliceConnector.java
@@ -120,10 +120,12 @@ class AliceConnector extends Connector {
 		if(remoteMatched) group.remoteConfirmationSucceeded();
 		else group.remoteConfirmationFailed();
 		if(!(localMatched && remoteMatched)) {
+			if(LOG.isLoggable(INFO))
+				LOG.info(pluginName + " confirmation failed");
 			tryToClose(conn, false);
 			return;
 		}
-		// The timestamp is taken after exhanging confirmation results
+		// The timestamp is taken after exchanging confirmation results
 		long localTimestamp = clock.currentTimeMillis();
 		// Confirmation succeeded - upgrade to a secure connection
 		if(LOG.isLoggable(INFO))
@@ -145,13 +147,19 @@ class AliceConnector extends Connector {
 		Author remoteAuthor;
 		long remoteTimestamp;
 		Map<TransportId, TransportProperties> remoteProps;
+		boolean remoteReuseConnection;
 		try {
 			sendPseudonym(w, aliceNonce);
 			sendTimestamp(w, localTimestamp);
 			sendTransportProperties(w);
+			sendConfirmation(w, reuseConnection);
 			remoteAuthor = receivePseudonym(r, bobNonce);
 			remoteTimestamp = receiveTimestamp(r);
 			remoteProps = receiveTransportProperties(r);
+			remoteReuseConnection = receiveConfirmation(r);
+			// Close the outgoing stream and expect EOF on the incoming stream
+			w.close();
+			if(!r.eof()) LOG.warning("Unexpected data at end of connection");
 		} catch(GeneralSecurityException e) {
 			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			group.pseudonymExchangeFailed();
@@ -174,12 +182,12 @@ class AliceConnector extends Connector {
 			group.pseudonymExchangeFailed();
 			return;
 		}
+		// Reuse the connection as a transport connection if both peers agree
+		if(reuseConnection && remoteReuseConnection) reuseConnection(conn);
+		else tryToClose(conn, false);
 		// Pseudonym exchange succeeded
 		if(LOG.isLoggable(INFO))
 			LOG.info(pluginName + " pseudonym exchange succeeded");
 		group.pseudonymExchangeSucceeded(remoteAuthor);
-		// Reuse the connection as an outgoing transport connection
-		if(reuseConnection) reuseConnection(conn, true);
-		else tryToClose(conn, false);
 	}
 }
\ No newline at end of file
diff --git a/briar-core/src/org/briarproject/invitation/BobConnector.java b/briar-core/src/org/briarproject/invitation/BobConnector.java
index dae8691920e1acf62cfc81c4af54feae020ba704..5dc5f1173791cf4c6b1a351ed576d1395cc33ab1 100644
--- a/briar-core/src/org/briarproject/invitation/BobConnector.java
+++ b/briar-core/src/org/briarproject/invitation/BobConnector.java
@@ -120,10 +120,12 @@ class BobConnector extends Connector {
 		if(remoteMatched) group.remoteConfirmationSucceeded();
 		else group.remoteConfirmationFailed();
 		if(!(localMatched && remoteMatched)) {
+			if(LOG.isLoggable(INFO))
+				LOG.info(pluginName + " confirmation failed");
 			tryToClose(conn, false);
 			return;
 		}
-		// The timestamp is taken after exhanging confirmation results
+		// The timestamp is taken after exchanging confirmation results
 		long localTimestamp = clock.currentTimeMillis();
 		// Confirmation succeeded - upgrade to a secure connection
 		if(LOG.isLoggable(INFO))
@@ -145,13 +147,19 @@ class BobConnector extends Connector {
 		Author remoteAuthor;
 		long remoteTimestamp;
 		Map<TransportId, TransportProperties> remoteProps;
+		boolean remoteReuseConnection;
 		try {
 			remoteAuthor = receivePseudonym(r, aliceNonce);
 			remoteTimestamp = receiveTimestamp(r);
 			remoteProps = receiveTransportProperties(r);
+			remoteReuseConnection = receiveConfirmation(r);
 			sendPseudonym(w, bobNonce);
 			sendTimestamp(w, localTimestamp);
 			sendTransportProperties(w);
+			sendConfirmation(w, reuseConnection);
+			// Close the outgoing stream and expect EOF on the incoming stream
+			w.close();
+			if(!r.eof()) LOG.warning("Unexpected data at end of connection");
 		} catch(GeneralSecurityException e) {
 			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			group.pseudonymExchangeFailed();
@@ -174,12 +182,12 @@ class BobConnector extends Connector {
 			group.pseudonymExchangeFailed();
 			return;
 		}
+		// Reuse the connection as a transport connection if both peers agree
+		if(reuseConnection && remoteReuseConnection) reuseConnection(conn);
+		else tryToClose(conn, false);
 		// Pseudonym exchange succeeded
 		if(LOG.isLoggable(INFO))
 			LOG.info(pluginName + " pseudonym exchange succeeded");
 		group.pseudonymExchangeSucceeded(remoteAuthor);
-		// Reuse the connection as an incoming transport connection
-		if(reuseConnection) reuseConnection(conn, false);
-		else tryToClose(conn, false);
 	}
 }
diff --git a/briar-core/src/org/briarproject/invitation/Connector.java b/briar-core/src/org/briarproject/invitation/Connector.java
index af944d5d7682b217e1ac3c3eef05c354700fbd31..61191730dda40eeca1e416d34d21994956ff9999 100644
--- a/briar-core/src/org/briarproject/invitation/Connector.java
+++ b/briar-core/src/org/briarproject/invitation/Connector.java
@@ -29,7 +29,6 @@ import org.briarproject.api.FormatException;
 import org.briarproject.api.LocalAuthor;
 import org.briarproject.api.TransportId;
 import org.briarproject.api.TransportProperties;
-import org.briarproject.api.UniqueId;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.KeyManager;
 import org.briarproject.api.crypto.KeyPair;
@@ -131,8 +130,9 @@ abstract class Connector extends Thread {
 	}
 
 	protected byte[] receivePublicKeyHash(Reader r) throws IOException {
-		byte[] b = r.readBytes(UniqueId.LENGTH);
-		if(b.length < UniqueId.LENGTH) throw new FormatException();
+		int hashLength = messageDigest.getDigestLength();
+		byte[] b = r.readBytes(hashLength);
+		if(b.length < hashLength) throw new FormatException();
 		if(LOG.isLoggable(INFO)) LOG.info(pluginName + " received hash");
 		return b;
 	}
@@ -166,19 +166,19 @@ abstract class Connector extends Thread {
 		return crypto.deriveMasterSecret(key, keyPair, alice);
 	}
 
-	protected void sendConfirmation(Writer w, boolean matched)
+	protected void sendConfirmation(Writer w, boolean confirmed)
 			throws IOException {
-		w.writeBoolean(matched);
+		w.writeBoolean(confirmed);
 		w.flush();
 		if(LOG.isLoggable(INFO))
-			LOG.info(pluginName + " sent confirmation: " + matched);
+			LOG.info(pluginName + " sent confirmation: " + confirmed);
 	}
 
 	protected boolean receiveConfirmation(Reader r) throws IOException {
-		boolean matched = r.readBoolean();
+		boolean confirmed = r.readBoolean();
 		if(LOG.isLoggable(INFO))
-			LOG.info(pluginName + " received confirmation: " + matched);
-		return matched;
+			LOG.info(pluginName + " received confirmation: " + confirmed);
+		return confirmed;
 	}
 
 	protected void sendPseudonym(Writer w, byte[] nonce)
@@ -317,13 +317,10 @@ abstract class Connector extends Thread {
 		}
 	}
 
-	protected void reuseConnection(DuplexTransportConnection conn,
-			boolean alice) {
+	protected void reuseConnection(DuplexTransportConnection conn) {
 		if(contactId == null) throw new IllegalStateException();
 		TransportId t = plugin.getId();
-		if(alice)
-			connectionManager.manageOutgoingConnection(contactId, t, conn);
-		else connectionManager.manageIncomingConnection(t, conn);
+		connectionManager.manageOutgoingConnection(contactId, t, conn);
 	}
 
 	private static class TransportIdComparator