diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
index 8ffd06213e6e2a90cfa38b58a00bcf34297d42f4..11631f22fda6db0351682106a9f0828d2c02e20f 100644
--- a/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
+++ b/briar-api/src/org/briarproject/api/crypto/CryptoComponent.java
@@ -36,11 +36,10 @@ public interface CryptoComponent {
 	int deriveBTConfirmationCode(SecretKey master, boolean alice);
 
 	/**
-	 * Derives a header key for an invitation stream from the given master
-	 * secret.
+	 * Derives a stream header key from the given master secret.
 	 * @param alice whether the key is for use by Alice or Bob.
 	 */
-	SecretKey deriveBTInvitationKey(SecretKey master, boolean alice);
+	SecretKey deriveHeaderKey(SecretKey master, boolean alice);
 
 	/**
 	 * Derives a nonce from the given master secret for one of the parties to
@@ -107,7 +106,7 @@ public interface CryptoComponent {
 	 * Derives a master secret from two public keys and one of the corresponding
 	 * private keys.
 	 * <p/>
-	 * Part of BQP. This is a helper method that calls
+	 * This is a helper method that calls
 	 * deriveMasterSecret(deriveSharedSecret(theirPublicKey, ourKeyPair, alice))
 	 *
 	 * @param theirPublicKey the ephemeral public key of the remote party
diff --git a/briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java b/briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java
index 7219460e6baec45801f9ff3a788c6e297c5d4761..943d02de98598359dedbf1767411a6334b8ed504 100644
--- a/briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java
+++ b/briar-core/src/org/briarproject/contact/ContactExchangeTaskImpl.java
@@ -93,6 +93,9 @@ public class ContactExchangeTaskImpl extends Thread
 
 	@Override
 	public void run() {
+		// Derive the header keys for the transport streams
+		SecretKey aliceHeaderKey = crypto.deriveHeaderKey(masterSecret, true);
+		SecretKey bobHeaderKey = crypto.deriveHeaderKey(masterSecret, false);
 		BdfReader r;
 		BdfWriter w;
 		try {
@@ -100,13 +103,13 @@ public class ContactExchangeTaskImpl extends Thread
 			InputStream streamReader =
 					streamReaderFactory.createInvitationStreamReader(
 							conn.getReader().getInputStream(),
-							masterSecret);
+							alice ? bobHeaderKey : aliceHeaderKey);
 			r = bdfReaderFactory.createReader(streamReader);
 			// Create the writers
 			OutputStream streamWriter =
 					streamWriterFactory.createInvitationStreamWriter(
 							conn.getWriter().getOutputStream(),
-							masterSecret);
+							alice ? aliceHeaderKey : bobHeaderKey);
 			w = bdfWriterFactory.createWriter(streamWriter);
 		} catch (IOException e) {
 			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
@@ -115,7 +118,7 @@ public class ContactExchangeTaskImpl extends Thread
 			return;
 		}
 
-		// Derive the invitation nonces
+		// Derive the nonces to be signed
 		byte[] aliceNonce = crypto.deriveSignatureNonce(masterSecret, true);
 		byte[] bobNonce = crypto.deriveSignatureNonce(masterSecret, false);
 
@@ -155,8 +158,8 @@ public class ContactExchangeTaskImpl extends Thread
 
 		try {
 			// Add the contact
-			ContactId contactId =
-					addContact(remoteAuthor, masterSecret, timestamp, true);
+			ContactId contactId = addContact(remoteAuthor, masterSecret,
+					timestamp, alice);
 			// Reuse the connection as a transport connection
 			connectionManager.manageOutgoingConnection(contactId, transportId,
 					conn);
diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
index c17f67901044af736af07dfc5f21e05c9536a809..825c3720f5188500ec89aa7a83fb70096b14270a 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
@@ -63,24 +63,22 @@ class CryptoComponentImpl implements CryptoComponent {
 		return s.getBytes(Charset.forName("US-ASCII"));
 	}
 
-	// KDF label for bluetooth master key derivation
-	private static final byte[] BT_MASTER = ascii("MASTER");
 	// KDF labels for bluetooth confirmation code derivation
 	private static final byte[] BT_A_CONFIRM = ascii("ALICE_CONFIRMATION_CODE");
 	private static final byte[] BT_B_CONFIRM = ascii("BOB_CONFIRMATION_CODE");
-	// KDF labels for bluetooth invitation stream header key derivation
-	private static final byte[] BT_A_INVITE = ascii("ALICE_INVITATION_KEY");
-	private static final byte[] BT_B_INVITE = ascii("BOB_INVITATION_KEY");
-	// KDF labels for bluetooth signature nonce derivation
-	private static final byte[] BT_A_NONCE = ascii("ALICE_SIGNATURE_NONCE");
-	private static final byte[] BT_B_NONCE = ascii("BOB_SIGNATURE_NONCE");
+	// KDF labels for contact exchange stream header key derivation
+	private static final byte[] A_INVITE = ascii("ALICE_INVITATION_KEY");
+	private static final byte[] B_INVITE = ascii("BOB_INVITATION_KEY");
+	// KDF labels for contact exchange signature nonce derivation
+	private static final byte[] A_SIG_NONCE = ascii("ALICE_SIGNATURE_NONCE");
+	private static final byte[] B_SIG_NONCE = ascii("BOB_SIGNATURE_NONCE");
 	// Hash label for BQP public key commitment derivation
 	private static final byte[] COMMIT = ascii("COMMIT");
-	// Hash label for BQP shared secret derivation
+	// Hash label for shared secret derivation
 	private static final byte[] SHARED_SECRET = ascii("SHARED_SECRET");
 	// KDF label for BQP confirmation key derivation
 	private static final byte[] CONFIRMATION_KEY = ascii("CONFIRMATION_KEY");
-	// KDF label for BQP master key derivation
+	// KDF label for master key derivation
 	private static final byte[] MASTER_KEY = ascii("MASTER_KEY");
 	// KDF labels for tag key derivation
 	private static final byte[] A_TAG = ascii("ALICE_TAG_KEY");
@@ -210,12 +208,14 @@ class CryptoComponentImpl implements CryptoComponent {
 		return ByteUtils.readUint(b, CODE_BITS);
 	}
 
-	public SecretKey deriveBTInvitationKey(SecretKey master, boolean alice) {
-		return new SecretKey(macKdf(master, alice ? BT_A_INVITE : BT_B_INVITE));
+	public SecretKey deriveHeaderKey(SecretKey master,
+			boolean alice) {
+		return new SecretKey(macKdf(master, alice ? A_INVITE : B_INVITE));
 	}
 
-	public byte[] deriveSignatureNonce(SecretKey master, boolean alice) {
-		return macKdf(master, alice ? BT_A_NONCE : BT_B_NONCE);
+	public byte[] deriveSignatureNonce(SecretKey master,
+			boolean alice) {
+		return macKdf(master, alice ? A_SIG_NONCE : B_SIG_NONCE);
 	}
 
 	public byte[] deriveKeyCommitment(byte[] publicKey) {
@@ -438,29 +438,6 @@ class CryptoComponentImpl implements CryptoComponent {
 		}
 	}
 
-	// Key derivation function based on a hash function - see NIST SP 800-56A,
-	// section 5.8
-	private byte[] hashKdf(byte[]... inputs) {
-		Digest digest = new Blake2sDigest();
-		// The output of the hash function must be long enough to use as a key
-		int hashLength = digest.getDigestSize();
-		if (hashLength < SecretKey.LENGTH) throw new IllegalStateException();
-		// Calculate the hash over the concatenated length-prefixed inputs
-		byte[] length = new byte[INT_32_BYTES];
-		for (byte[] input : inputs) {
-			ByteUtils.writeUint32(input.length, length, 0);
-			digest.update(length, 0, length.length);
-			digest.update(input, 0, input.length);
-		}
-		byte[] hash = new byte[hashLength];
-		digest.doFinal(hash, 0);
-		// The output is the first SecretKey.LENGTH bytes of the hash
-		if (hash.length == SecretKey.LENGTH) return hash;
-		byte[] truncated = new byte[SecretKey.LENGTH];
-		System.arraycopy(hash, 0, truncated, 0, truncated.length);
-		return truncated;
-	}
-
 	// Key derivation function based on a pseudo-random function - see
 	// NIST SP 800-108, section 5.1
 	private byte[] macKdf(SecretKey key, byte[]... inputs) {
diff --git a/briar-core/src/org/briarproject/invitation/AliceConnector.java b/briar-core/src/org/briarproject/invitation/AliceConnector.java
index fc02774043417d8dc57bf443f4e54cb4941c8d93..b2947ece4db90335101bc6cb4d1a82424cbaa8a6 100644
--- a/briar-core/src/org/briarproject/invitation/AliceConnector.java
+++ b/briar-core/src/org/briarproject/invitation/AliceConnector.java
@@ -125,8 +125,8 @@ class AliceConnector extends Connector {
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " confirmation succeeded");
 		// Derive the header keys
-		SecretKey aliceHeaderKey = crypto.deriveBTInvitationKey(master, true);
-		SecretKey bobHeaderKey = crypto.deriveBTInvitationKey(master, false);
+		SecretKey aliceHeaderKey = crypto.deriveHeaderKey(master, true);
+		SecretKey bobHeaderKey = crypto.deriveHeaderKey(master, false);
 		// Create the readers
 		InputStream streamReader =
 				streamReaderFactory.createInvitationStreamReader(in,
diff --git a/briar-core/src/org/briarproject/invitation/BobConnector.java b/briar-core/src/org/briarproject/invitation/BobConnector.java
index 2f1cfc2e8dcf2a1e4b826fa66d0ca5837e155f43..1460b953ec1b3ec222ca14fc5e27ebfc93447966 100644
--- a/briar-core/src/org/briarproject/invitation/BobConnector.java
+++ b/briar-core/src/org/briarproject/invitation/BobConnector.java
@@ -125,8 +125,10 @@ class BobConnector extends Connector {
 		if (LOG.isLoggable(INFO))
 			LOG.info(pluginName + " confirmation succeeded");
 		// Derive the header keys
-		SecretKey aliceHeaderKey = crypto.deriveBTInvitationKey(master, true);
-		SecretKey bobHeaderKey = crypto.deriveBTInvitationKey(master, false);
+		SecretKey aliceHeaderKey = crypto.deriveHeaderKey(master,
+				true);
+		SecretKey bobHeaderKey = crypto.deriveHeaderKey(master,
+				false);
 		// Create the readers
 		InputStream streamReader =
 				streamReaderFactory.createInvitationStreamReader(in,
@@ -138,8 +140,10 @@ class BobConnector extends Connector {
 						bobHeaderKey);
 		w = bdfWriterFactory.createWriter(streamWriter);
 		// Derive the nonces
-		byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
-		byte[] bobNonce = crypto.deriveSignatureNonce(master, false);
+		byte[] aliceNonce = crypto.deriveSignatureNonce(master,
+				true);
+		byte[] bobNonce = crypto.deriveSignatureNonce(master,
+				false);
 		// Exchange pseudonyms, signed nonces and timestamps
 		Author remoteAuthor;
 		long remoteTimestamp;