diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
index 8685f56ac77b995d3172f01c28e2701dc97ef6f2..be63cd61783c7ef10c255d0a887f4c305038936f 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
@@ -336,7 +336,7 @@ class CryptoComponentImpl implements CryptoComponent {
 		int macBytes = cipher.getMacBytes();
 		// The input contains the salt, iterations, IV, ciphertext and MAC
 		if(input.length < PBKDF_SALT_BYTES + 4 + STORAGE_IV_BYTES + macBytes)
-			return null; // Invalid
+			return null; // Invalid input
 		byte[] salt = new byte[PBKDF_SALT_BYTES];
 		System.arraycopy(input, 0, salt, 0, salt.length);
 		long iterations = ByteUtils.readUint32(input, salt.length);
@@ -366,28 +366,21 @@ class CryptoComponentImpl implements CryptoComponent {
 
 	// Key derivation function based on a hash function - see NIST SP 800-56A,
 	// section 5.8
-	private byte[] concatenationKdf(byte[] rawSecret, byte[] label,
-			byte[] initiatorInfo, byte[] responderInfo) {
+	private byte[] concatenationKdf(byte[]... args) {
 		// The output of the hash function must be long enough to use as a key
 		MessageDigest messageDigest = getMessageDigest();
 		if(messageDigest.getDigestLength() < CIPHER_KEY_BYTES)
 			throw new RuntimeException();
-		// The length of every field must fit in an unsigned 8-bit integer
-		if(rawSecret.length > 255) throw new IllegalArgumentException();
-		if(label.length > 255) throw new IllegalArgumentException();
-		if(initiatorInfo.length > 255) throw new IllegalArgumentException();
-		if(responderInfo.length > 255) throw new IllegalArgumentException();
-		// All fields are length-prefixed
-		messageDigest.update((byte) rawSecret.length);
-		messageDigest.update(rawSecret);
-		messageDigest.update((byte) label.length);
-		messageDigest.update(label);
-		messageDigest.update((byte) initiatorInfo.length);
-		messageDigest.update(initiatorInfo);
-		messageDigest.update((byte) responderInfo.length);
-		messageDigest.update(responderInfo);
+		// Each argument is length-prefixed - the length must fit in an
+		// unsigned 8-bit integer
+		for(byte[] arg : args) {
+			if(arg.length > 255) throw new IllegalArgumentException();
+			messageDigest.update((byte) arg.length);
+			messageDigest.update(arg);
+		}
 		byte[] hash = messageDigest.digest();
-		// The secret is the first CIPHER_KEY_BYTES bytes of the hash
+		// The output is the first CIPHER_KEY_BYTES bytes of the hash
+		if(hash.length == CIPHER_KEY_BYTES) return hash;
 		byte[] output = new byte[CIPHER_KEY_BYTES];
 		System.arraycopy(hash, 0, output, 0, output.length);
 		return output;
@@ -410,7 +403,7 @@ class CryptoComponentImpl implements CryptoComponent {
 		int macLength = prf.getMacSize();
 		// The output of the PRF must be long enough to use as a key
 		if(macLength < CIPHER_KEY_BYTES) throw new RuntimeException();
-		byte[] mac = new byte[macLength], output = new byte[CIPHER_KEY_BYTES];
+		byte[] mac = new byte[macLength];
 		prf.update((byte) 0); // Counter
 		prf.update(label, 0, label.length); // Null-terminated
 		byte[] contextBytes = new byte[4];
@@ -418,6 +411,9 @@ class CryptoComponentImpl implements CryptoComponent {
 		prf.update(contextBytes, 0, contextBytes.length);
 		prf.update((byte) CIPHER_KEY_BYTES); // Output length
 		prf.doFinal(mac, 0);
+		// The output is the first CIPHER_KEY_BYTES bytes of the MAC
+		if(mac.length == CIPHER_KEY_BYTES) return mac;
+		byte[] output = new byte[CIPHER_KEY_BYTES];
 		System.arraycopy(mac, 0, output, 0, output.length);
 		return output;
 	}
diff --git a/briar-core/src/org/briarproject/crypto/CryptoModule.java b/briar-core/src/org/briarproject/crypto/CryptoModule.java
index d4ac20c6495d50fd7c21f3c8a339a0579cb8ec9b..3cdaf74041683bae608eb3cfcdf890939daeeb4c 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoModule.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoModule.java
@@ -42,6 +42,7 @@ public class CryptoModule extends AbstractModule {
 
 	@Override
 	protected void configure() {
+		bind(AuthenticatedCipher.class).to(AuthenticatedCipherImpl.class);
 		bind(CryptoComponent.class).to(
 				CryptoComponentImpl.class).in(Singleton.class);
 		bind(PasswordStrengthEstimator.class).to(
diff --git a/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java b/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java
index 23ea5e245ccd6925d73414ac4644c0eee339310c..205fc2e5e2de488d71a40278173b9176d13d0da8 100644
--- a/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java
+++ b/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java
@@ -3,6 +3,7 @@ package org.briarproject.crypto;
 import java.io.InputStream;
 
 import javax.inject.Inject;
+import javax.inject.Provider;
 
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.SecretKey;
@@ -13,10 +14,13 @@ import org.briarproject.api.transport.StreamContext;
 class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
 
 	private final CryptoComponent crypto;
+	private final Provider<AuthenticatedCipher> cipherProvider;
 
 	@Inject
-	StreamDecrypterFactoryImpl(CryptoComponent crypto) {
+	StreamDecrypterFactoryImpl(CryptoComponent crypto,
+			Provider<AuthenticatedCipher> cipherProvider) {
 		this.crypto = crypto;
+		this.cipherProvider = cipherProvider;
 	}
 
 	public StreamDecrypter createStreamDecrypter(InputStream in,
@@ -27,7 +31,7 @@ class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
 		boolean alice = !ctx.getAlice();
 		SecretKey frameKey = crypto.deriveFrameKey(secret, streamNumber, alice);
 		// Create the decrypter
-		AuthenticatedCipher cipher = new AuthenticatedCipherImpl();
+		AuthenticatedCipher cipher = cipherProvider.get();
 		return new StreamDecrypterImpl(in, cipher, frameKey);
 	}
 
@@ -36,7 +40,7 @@ class StreamDecrypterFactoryImpl implements StreamDecrypterFactory {
 		// Derive the frame key
 		SecretKey frameKey = crypto.deriveFrameKey(secret, 0, alice);
 		// Create the decrypter
-		AuthenticatedCipher cipher = new AuthenticatedCipherImpl();
+		AuthenticatedCipher cipher = cipherProvider.get();
 		return new StreamDecrypterImpl(in, cipher, frameKey);
 	}
 }
diff --git a/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java b/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java
index ae0429e05e952b8f60699767291f9e837e2e2841..90fd2af20e97deb33a7668f07e91c49be02ffcb7 100644
--- a/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java
+++ b/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java
@@ -5,6 +5,7 @@ import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
 import java.io.OutputStream;
 
 import javax.inject.Inject;
+import javax.inject.Provider;
 
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.SecretKey;
@@ -15,10 +16,13 @@ import org.briarproject.api.transport.StreamContext;
 class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
 
 	private final CryptoComponent crypto;
+	private final Provider<AuthenticatedCipher> cipherProvider;
 
 	@Inject
-	StreamEncrypterFactoryImpl(CryptoComponent crypto) {
+	StreamEncrypterFactoryImpl(CryptoComponent crypto,
+			Provider<AuthenticatedCipher> cipherProvider) {
 		this.crypto = crypto;
+		this.cipherProvider = cipherProvider;
 	}
 
 	public StreamEncrypter createStreamEncrypter(OutputStream out,
@@ -33,7 +37,7 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
 		// Derive the frame key
 		SecretKey frameKey = crypto.deriveFrameKey(secret, streamNumber, alice);
 		// Create the encrypter
-		AuthenticatedCipher cipher = new AuthenticatedCipherImpl();
+		AuthenticatedCipher cipher = cipherProvider.get();
 		return new StreamEncrypterImpl(out, cipher, frameKey, tag);
 	}
 
@@ -42,7 +46,7 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
 		// Derive the frame key
 		SecretKey frameKey = crypto.deriveFrameKey(secret, 0, alice);
 		// Create the encrypter
-		AuthenticatedCipher cipher = new AuthenticatedCipherImpl();
+		AuthenticatedCipher cipher = cipherProvider.get();
 		return new StreamEncrypterImpl(out, cipher, frameKey, null);
 	}
 }