From f3fdd859962fe96e3b9a1d9651095c7c190b6098 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Fri, 2 Dec 2011 12:02:55 +0000
Subject: [PATCH] Renamed "encrypted IVs" as "tags" (actual crypto changes to
 follow).

---
 .../sf/briar/api/crypto/CryptoComponent.java  |   6 +-
 .../api/transport/BatchConnectionFactory.java |   2 +-
 .../transport/ConnectionReaderFactory.java    |   2 +-
 .../api/transport/ConnectionRecogniser.java   |   3 +-
 .../transport/ConnectionWriterFactory.java    |   2 +-
 .../transport/StreamConnectionFactory.java    |   2 +-
 .../api/transport/TransportConstants.java     |   4 +-
 .../sf/briar/crypto/CryptoComponentImpl.java  |  26 ++--
 .../transport/ConnectionDecrypterImpl.java    |   6 +-
 .../transport/ConnectionDispatcherImpl.java   |  24 ++--
 .../transport/ConnectionEncrypterImpl.java    |  37 +++--
 .../ConnectionReaderFactoryImpl.java          |  16 +--
 .../transport/ConnectionRecogniserImpl.java   |  36 ++---
 .../ConnectionWriterFactoryImpl.java          |  22 +--
 .../net/sf/briar/transport/IvEncoder.java     |  12 +-
 .../batch/BatchConnectionFactoryImpl.java     |   4 +-
 .../batch/IncomingBatchConnection.java        |   9 +-
 .../stream/IncomingStreamConnection.java      |  10 +-
 .../stream/StreamConnectionFactoryImpl.java   |   4 +-
 .../net/sf/briar/ProtocolIntegrationTest.java |   7 +-
 .../sf/briar/crypto/KeyDerivationTest.java    |   4 +-
 .../ConnectionDecrypterImplTest.java          |  16 +--
 .../ConnectionEncrypterImplTest.java          |  20 +--
 .../ConnectionRecogniserImplTest.java         | 136 +++++++++---------
 .../briar/transport/FrameReadWriteTest.java   |  30 ++--
 .../batch/BatchConnectionReadWriteTest.java   |  12 +-
 26 files changed, 225 insertions(+), 227 deletions(-)

diff --git a/api/net/sf/briar/api/crypto/CryptoComponent.java b/api/net/sf/briar/api/crypto/CryptoComponent.java
index a764e33bc1..25b4239c24 100644
--- a/api/net/sf/briar/api/crypto/CryptoComponent.java
+++ b/api/net/sf/briar/api/crypto/CryptoComponent.java
@@ -11,7 +11,7 @@ public interface CryptoComponent {
 
 	ErasableKey deriveFrameKey(byte[] secret, boolean initiator);
 
-	ErasableKey deriveIvKey(byte[] secret, boolean initiator);
+	ErasableKey deriveTagKey(byte[] secret, boolean initiator);
 
 	ErasableKey deriveMacKey(byte[] secret, boolean initiator);
 
@@ -23,8 +23,6 @@ public interface CryptoComponent {
 
 	Cipher getFrameCipher();
 
-	Cipher getIvCipher();
-
 	KeyParser getKeyParser();
 
 	Mac getMac();
@@ -34,4 +32,6 @@ public interface CryptoComponent {
 	SecureRandom getSecureRandom();
 
 	Signature getSignature();
+
+	Cipher getTagCipher();
 }
diff --git a/api/net/sf/briar/api/transport/BatchConnectionFactory.java b/api/net/sf/briar/api/transport/BatchConnectionFactory.java
index 279e605256..eab7395aab 100644
--- a/api/net/sf/briar/api/transport/BatchConnectionFactory.java
+++ b/api/net/sf/briar/api/transport/BatchConnectionFactory.java
@@ -6,7 +6,7 @@ import net.sf.briar.api.protocol.TransportIndex;
 public interface BatchConnectionFactory {
 
 	void createIncomingConnection(ConnectionContext ctx,
-			BatchTransportReader r, byte[] encryptedIv);
+			BatchTransportReader r, byte[] tag);
 
 	void createOutgoingConnection(ContactId c, TransportIndex i,
 			BatchTransportWriter w);
diff --git a/api/net/sf/briar/api/transport/ConnectionReaderFactory.java b/api/net/sf/briar/api/transport/ConnectionReaderFactory.java
index a916be465e..ab65da7fec 100644
--- a/api/net/sf/briar/api/transport/ConnectionReaderFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionReaderFactory.java
@@ -9,7 +9,7 @@ public interface ConnectionReaderFactory {
 	 * initiator's side of a stream-mode connection.
 	 */
 	ConnectionReader createConnectionReader(InputStream in,
-			ConnectionContext ctx, byte[] encryptedIv);
+			ConnectionContext ctx, byte[] tag);
 
 	/**
 	 * Creates a connection reader for the responder's side of a stream-mode
diff --git a/api/net/sf/briar/api/transport/ConnectionRecogniser.java b/api/net/sf/briar/api/transport/ConnectionRecogniser.java
index dc12799b3c..7e23e370ab 100644
--- a/api/net/sf/briar/api/transport/ConnectionRecogniser.java
+++ b/api/net/sf/briar/api/transport/ConnectionRecogniser.java
@@ -13,8 +13,7 @@ public interface ConnectionRecogniser {
 	 * Asynchronously calls one of the callback's connectionAccepted(),
 	 * connectionRejected() or handleException() methods.
 	 */
-	void acceptConnection(TransportId t, byte[] encryptedIv,
-			Callback c);
+	void acceptConnection(TransportId t, byte[] tag, Callback c);
 
 	interface Callback {
 
diff --git a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
index c999efd7e9..0713e3724c 100644
--- a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
+++ b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java
@@ -16,5 +16,5 @@ public interface ConnectionWriterFactory {
 	 * connection.
 	 */
 	ConnectionWriter createConnectionWriter(OutputStream out, long capacity,
-			ConnectionContext ctx, byte[] encryptedIv);
+			ConnectionContext ctx, byte[] tag);
 }
diff --git a/api/net/sf/briar/api/transport/StreamConnectionFactory.java b/api/net/sf/briar/api/transport/StreamConnectionFactory.java
index 13c1daf69e..1cabf37e33 100644
--- a/api/net/sf/briar/api/transport/StreamConnectionFactory.java
+++ b/api/net/sf/briar/api/transport/StreamConnectionFactory.java
@@ -6,7 +6,7 @@ import net.sf.briar.api.protocol.TransportIndex;
 public interface StreamConnectionFactory {
 
 	void createIncomingConnection(ConnectionContext ctx,
-			StreamTransportConnection s, byte[] encryptedIv);
+			StreamTransportConnection s, byte[] tag);
 
 	void createOutgoingConnection(ContactId c, TransportIndex i,
 			StreamTransportConnection s);
diff --git a/api/net/sf/briar/api/transport/TransportConstants.java b/api/net/sf/briar/api/transport/TransportConstants.java
index 7be2a44391..d567504b9a 100644
--- a/api/net/sf/briar/api/transport/TransportConstants.java
+++ b/api/net/sf/briar/api/transport/TransportConstants.java
@@ -8,10 +8,10 @@ public interface TransportConstants {
 	static final int MAX_FRAME_LENGTH = 65536; // 2^16, 64 KiB
 
 	/**
-	 * The length in bytes of the encrypted IV that uniquely identifies a
+	 * The length in bytes of the pseudo-random tag that uniquely identifies a
 	 * connection.
 	 */
-	static final int IV_LENGTH = 16;
+	static final int TAG_LENGTH = 16;
 
 	/**
 	 * The minimum connection length in bytes that all transport plugins must
diff --git a/components/net/sf/briar/crypto/CryptoComponentImpl.java b/components/net/sf/briar/crypto/CryptoComponentImpl.java
index 2580d2ab25..34eeea8bd8 100644
--- a/components/net/sf/briar/crypto/CryptoComponentImpl.java
+++ b/components/net/sf/briar/crypto/CryptoComponentImpl.java
@@ -30,7 +30,7 @@ class CryptoComponentImpl implements CryptoComponent {
 	private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding";
 	private static final String SECRET_KEY_ALGO = "AES";
 	private static final int SECRET_KEY_BYTES = 32; // 256 bits
-	private static final String IV_CIPHER_ALGO = "AES/ECB/NoPadding";
+	private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding";
 	private static final String MAC_ALGO = "HMacSHA256";
 	private static final String SIGNATURE_ALGO = "ECDSA";
 	private static final String KEY_DERIVATION_ALGO = "AES/CTR/NoPadding";
@@ -38,7 +38,7 @@ class CryptoComponentImpl implements CryptoComponent {
 
 	// Labels for key derivation, null-terminated
 	private static final byte[] FRAME = { 'F', 'R', 'A', 'M', 'E', 0 };
-	private static final byte[] IV = { 'I', 'V', 0 };
+	private static final byte[] TAG = { 'T', 'A', 'G', 0 };
 	private static final byte[] MAC = { 'M', 'A', 'C', 0 };
 	private static final byte[] NEXT = { 'N', 'E', 'X', 'T', 0 };
 	// Context strings for key derivation
@@ -71,9 +71,9 @@ class CryptoComponentImpl implements CryptoComponent {
 		else return deriveKey(secret, FRAME, RESPONDER);
 	}
 
-	public ErasableKey deriveIvKey(byte[] secret, boolean initiator) {
-		if(initiator) return deriveKey(secret, IV, INITIATOR);
-		else return deriveKey(secret, IV, RESPONDER);
+	public ErasableKey deriveTagKey(byte[] secret, boolean initiator) {
+		if(initiator) return deriveKey(secret, TAG, INITIATOR);
+		else return deriveKey(secret, TAG, RESPONDER);
 	}
 
 	public ErasableKey deriveMacKey(byte[] secret, boolean initiator) {
@@ -143,14 +143,6 @@ class CryptoComponentImpl implements CryptoComponent {
 		}
 	}
 
-	public Cipher getIvCipher() {
-		try {
-			return Cipher.getInstance(IV_CIPHER_ALGO, PROVIDER);
-		} catch(GeneralSecurityException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
 	public KeyParser getKeyParser() {
 		return keyParser;
 	}
@@ -183,4 +175,12 @@ class CryptoComponentImpl implements CryptoComponent {
 			throw new RuntimeException(e);
 		}
 	}
+
+	public Cipher getTagCipher() {
+		try {
+			return Cipher.getInstance(TAG_CIPHER_ALGO, PROVIDER);
+		} catch(GeneralSecurityException e) {
+			throw new RuntimeException(e);
+		}
+	}
 }
diff --git a/components/net/sf/briar/transport/ConnectionDecrypterImpl.java b/components/net/sf/briar/transport/ConnectionDecrypterImpl.java
index 0232dd4e71..7eb56ab101 100644
--- a/components/net/sf/briar/transport/ConnectionDecrypterImpl.java
+++ b/components/net/sf/briar/transport/ConnectionDecrypterImpl.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 
 import java.io.EOFException;
@@ -31,11 +31,11 @@ implements ConnectionDecrypter {
 	ConnectionDecrypterImpl(InputStream in, byte[] iv, Cipher frameCipher,
 			ErasableKey frameKey) {
 		super(in);
-		if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
+		if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
 		this.iv = iv;
 		this.frameCipher = frameCipher;
 		this.frameKey = frameKey;
-		buf = new byte[IV_LENGTH];
+		buf = new byte[TAG_LENGTH];
 	}
 
 	public InputStream getInputStream() {
diff --git a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java
index 54cce8ab0d..e2a49f6bd7 100644
--- a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java
+++ b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java
@@ -41,20 +41,20 @@ class ConnectionDispatcherImpl implements ConnectionDispatcher {
 	}
 
 	public void dispatchReader(TransportId t, final BatchTransportReader r) {
-		// Read the encrypted IV
-		final byte[] encryptedIv;
+		// Read the tag
+		final byte[] tag;
 		try {
-			encryptedIv = readIv(r.getInputStream());
+			tag = readTag(r.getInputStream());
 		} catch(IOException e) {
 			if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
 			r.dispose(false);
 			return;
 		}
 		// Get the connection context asynchronously
-		recogniser.acceptConnection(t, encryptedIv, new Callback() {
+		recogniser.acceptConnection(t, tag, new Callback() {
 
 			public void connectionAccepted(ConnectionContext ctx) {
-				batchConnFactory.createIncomingConnection(ctx, r, encryptedIv);
+				batchConnFactory.createIncomingConnection(ctx, r, tag);
 			}
 
 			public void connectionRejected() {
@@ -68,8 +68,8 @@ class ConnectionDispatcherImpl implements ConnectionDispatcher {
 		});
 	}
 
-	private byte[] readIv(InputStream in) throws IOException {
-		byte[] b = new byte[TransportConstants.IV_LENGTH];
+	private byte[] readTag(InputStream in) throws IOException {
+		byte[] b = new byte[TransportConstants.TAG_LENGTH];
 		int offset = 0;
 		while(offset < b.length) {
 			int read = in.read(b, offset, b.length - offset);
@@ -86,20 +86,20 @@ class ConnectionDispatcherImpl implements ConnectionDispatcher {
 
 	public void dispatchIncomingConnection(TransportId t,
 			final StreamTransportConnection s) {
-		// Read the encrypted IV
-		final byte[] encryptedIv;
+		// Read the tag
+		final byte[] tag;
 		try {
-			encryptedIv = readIv(s.getInputStream());
+			tag = readTag(s.getInputStream());
 		} catch(IOException e) {
 			if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
 			s.dispose(false);
 			return;
 		}
 		// Get the connection context asynchronously
-		recogniser.acceptConnection(t, encryptedIv, new Callback() {
+		recogniser.acceptConnection(t, tag, new Callback() {
 
 			public void connectionAccepted(ConnectionContext ctx) {
-				streamConnFactory.createIncomingConnection(ctx, s, encryptedIv);
+				streamConnFactory.createIncomingConnection(ctx, s, tag);
 			}
 
 			public void connectionRejected() {
diff --git a/components/net/sf/briar/transport/ConnectionEncrypterImpl.java b/components/net/sf/briar/transport/ConnectionEncrypterImpl.java
index 79066fac1c..0eb7ff5111 100644
--- a/components/net/sf/briar/transport/ConnectionEncrypterImpl.java
+++ b/components/net/sf/briar/transport/ConnectionEncrypterImpl.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
 
 import java.io.FilterOutputStream;
@@ -20,23 +20,23 @@ implements ConnectionEncrypter {
 
 	private final Cipher frameCipher;
 	private final ErasableKey frameKey;
-	private final byte[] iv, encryptedIv;
+	private final byte[] iv, tag;
 
 	private long capacity, frame = 0L;
-	private boolean ivWritten = false, betweenFrames = false;
+	private boolean tagWritten = false, betweenFrames = false;
 
 	ConnectionEncrypterImpl(OutputStream out, long capacity, byte[] iv,
-			Cipher ivCipher, Cipher frameCipher, ErasableKey ivKey,
+			Cipher tagCipher, Cipher frameCipher, ErasableKey tagKey,
 			ErasableKey frameKey) {
 		super(out);
 		this.capacity = capacity;
 		this.iv = iv;
 		this.frameCipher = frameCipher;
 		this.frameKey = frameKey;
-		// Encrypt the IV
+		// Encrypt the tag
 		try {
-			ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
-			encryptedIv = ivCipher.doFinal(iv);
+			tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
+			tag = tagCipher.doFinal(iv);
 		} catch(BadPaddingException badCipher) {
 			throw new IllegalArgumentException(badCipher);
 		} catch(IllegalBlockSizeException badCipher) {
@@ -44,9 +44,8 @@ implements ConnectionEncrypter {
 		} catch(InvalidKeyException badKey) {
 			throw new IllegalArgumentException(badKey);
 		}
-		if(encryptedIv.length != IV_LENGTH)
-			throw new IllegalArgumentException();
-		ivKey.erase();
+		if(tag.length != TAG_LENGTH) throw new IllegalArgumentException();
+		tagKey.erase();
 	}
 
 	public OutputStream getOutputStream() {
@@ -55,7 +54,7 @@ implements ConnectionEncrypter {
 
 	public void writeMac(byte[] mac) throws IOException {
 		try {
-			if(!ivWritten || betweenFrames) throw new IllegalStateException();
+			if(!tagWritten || betweenFrames) throw new IllegalStateException();
 			try {
 				out.write(frameCipher.doFinal(mac));
 			} catch(BadPaddingException badCipher) {
@@ -78,7 +77,7 @@ implements ConnectionEncrypter {
 	@Override
 	public void write(int b) throws IOException {
 		try {
-			if(!ivWritten) writeIv();
+			if(!tagWritten) writeTag();
 			if(betweenFrames) initialiseCipher();
 			byte[] ciphertext = frameCipher.update(new byte[] {(byte) b});
 			if(ciphertext != null) out.write(ciphertext);
@@ -97,7 +96,7 @@ implements ConnectionEncrypter {
 	@Override
 	public void write(byte[] b, int off, int len) throws IOException {
 		try {
-			if(!ivWritten) writeIv();
+			if(!tagWritten) writeTag();
 			if(betweenFrames) initialiseCipher();
 			byte[] ciphertext = frameCipher.update(b, off, len);
 			if(ciphertext != null) out.write(ciphertext);
@@ -108,17 +107,17 @@ implements ConnectionEncrypter {
 		}
 	}
 
-	private void writeIv() throws IOException {
-		assert !ivWritten;
+	private void writeTag() throws IOException {
+		assert !tagWritten;
 		assert !betweenFrames;
-		out.write(encryptedIv);
-		capacity -= encryptedIv.length;
-		ivWritten = true;
+		out.write(tag);
+		capacity -= tag.length;
+		tagWritten = true;
 		betweenFrames = true;
 	}
 
 	private void initialiseCipher() {
-		assert ivWritten;
+		assert tagWritten;
 		assert betweenFrames;
 		if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
 		IvEncoder.updateIv(iv, frame);
diff --git a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
index 741546d2a9..6ad7b806f8 100644
--- a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java
@@ -27,14 +27,14 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
 	}
 
 	public ConnectionReader createConnectionReader(InputStream in,
-			ConnectionContext ctx, byte[] encryptedIv) {
-		// Decrypt the IV
-		Cipher ivCipher = crypto.getIvCipher();
-		ErasableKey ivKey = crypto.deriveIvKey(ctx.getSecret(), true);
+			ConnectionContext ctx, byte[] tag) {
+		// Decrypt the tag
+		Cipher tagCipher = crypto.getTagCipher();
+		ErasableKey tagKey = crypto.deriveTagKey(ctx.getSecret(), true);
 		byte[] iv;
 		try {
-			ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
-			iv = ivCipher.doFinal(encryptedIv);
+			tagCipher.init(Cipher.DECRYPT_MODE, tagKey);
+			iv = tagCipher.doFinal(tag);
 		} catch(BadPaddingException badCipher) {
 			throw new IllegalArgumentException(badCipher);
 		} catch(IllegalBlockSizeException badCipher) {
@@ -42,8 +42,8 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
 		} catch(InvalidKeyException badKey) {
 			throw new IllegalArgumentException(badKey);
 		}
-		ivKey.erase();
-		// Validate the IV
+		tagKey.erase();
+		// Validate the tag
 		int index = ctx.getTransportIndex().getInt();
 		long connection = ctx.getConnectionNumber();
 		if(!IvEncoder.validateIv(iv, index, connection))
diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
index 9150586b13..e365d6a99c 100644
--- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
+++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 
 import java.security.InvalidKeyException;
 import java.util.ArrayList;
@@ -50,7 +50,7 @@ DatabaseListener {
 	private final CryptoComponent crypto;
 	private final DatabaseComponent db;
 	private final Executor executor;
-	private final Cipher ivCipher; // Locking: this
+	private final Cipher tagCipher; // Locking: this
 	private final Set<TransportId> localTransportIds; // Locking: this
 	private final Map<Bytes, Context> expected; // Locking: this
 
@@ -62,7 +62,7 @@ DatabaseListener {
 		this.crypto = crypto;
 		this.db = db;
 		this.executor = executor;
-		ivCipher = crypto.getIvCipher();
+		tagCipher = crypto.getTagCipher();
 		localTransportIds = new HashSet<TransportId>();
 		expected = new HashMap<Bytes, Context>();
 	}
@@ -87,7 +87,7 @@ DatabaseListener {
 					ConnectionWindow w = db.getConnectionWindow(c, i);
 					for(Entry<Long, byte[]> e : w.getUnseen().entrySet()) {
 						Context ctx = new Context(c, t, i, e.getKey());
-						ivs.put(calculateIv(ctx, e.getValue()), ctx);
+						ivs.put(calculateTag(ctx, e.getValue()), ctx);
 					}
 					w.erase();
 				}
@@ -102,14 +102,14 @@ DatabaseListener {
 	}
 
 	// Locking: this
-	private Bytes calculateIv(Context ctx, byte[] secret) {
+	private Bytes calculateTag(Context ctx, byte[] secret) {
 		byte[] iv = IvEncoder.encodeIv(ctx.transportIndex.getInt(),
 				ctx.connection);
-		ErasableKey ivKey = crypto.deriveIvKey(secret, true);
+		ErasableKey tagKey = crypto.deriveTagKey(secret, true);
 		try {
-			ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
-			byte[] encryptedIv = ivCipher.doFinal(iv);
-			return new Bytes(encryptedIv);
+			tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
+			byte[] tag = tagCipher.doFinal(iv);
+			return new Bytes(tag);
 		} catch(BadPaddingException badCipher) {
 			throw new RuntimeException(badCipher);
 		} catch(IllegalBlockSizeException badCipher) {
@@ -117,16 +117,16 @@ DatabaseListener {
 		} catch(InvalidKeyException badKey) {
 			throw new RuntimeException(badKey);
 		} finally {
-			ivKey.erase();
+			tagKey.erase();
 		}
 	}
 
-	public void acceptConnection(final TransportId t, final byte[] encryptedIv,
+	public void acceptConnection(final TransportId t, final byte[] tag,
 			final Callback callback) {
 		executor.execute(new Runnable() {
 			public void run() {
 				try {
-					ConnectionContext ctx = acceptConnection(t, encryptedIv);
+					ConnectionContext ctx = acceptConnection(t, tag);
 					if(ctx == null) callback.connectionRejected();
 					else callback.connectionAccepted(ctx);
 				} catch(DbException e) {
@@ -137,13 +137,13 @@ DatabaseListener {
 	}
 
 	// Package access for testing
-	ConnectionContext acceptConnection(TransportId t, byte[] encryptedIv)
+	ConnectionContext acceptConnection(TransportId t, byte[] tag)
 	throws DbException {
-		if(encryptedIv.length != IV_LENGTH)
+		if(tag.length != TAG_LENGTH)
 			throw new IllegalArgumentException();
 		synchronized(this) {
 			if(!initialised) initialise();
-			Bytes b = new Bytes(encryptedIv);
+			Bytes b = new Bytes(tag);
 			Context ctx = expected.get(b);
 			if(ctx == null || !ctx.transportId.equals(t)) return null;
 			// The IV was expected
@@ -173,7 +173,7 @@ DatabaseListener {
 			}
 			for(Entry<Long, byte[]> e : w.getUnseen().entrySet()) {
 				Context ctx1 = new Context(c, t, i, e.getKey());
-				expected.put(calculateIv(ctx1, e.getValue()), ctx1);
+				expected.put(calculateTag(ctx1, e.getValue()), ctx1);
 			}
 			w.erase();
 			return new ConnectionContextImpl(c, i, connection, secret);
@@ -227,7 +227,7 @@ DatabaseListener {
 					ConnectionWindow w = db.getConnectionWindow(c, i);
 					for(Entry<Long, byte[]> e : w.getUnseen().entrySet()) {
 						Context ctx = new Context(c, t, i, e.getKey());
-						ivs.put(calculateIv(ctx, e.getValue()), ctx);
+						ivs.put(calculateTag(ctx, e.getValue()), ctx);
 					}
 					w.erase();
 				} catch(NoSuchContactException e) {
@@ -256,7 +256,7 @@ DatabaseListener {
 				ConnectionWindow w = db.getConnectionWindow(c, i);
 				for(Entry<Long, byte[]> e : w.getUnseen().entrySet()) {
 					Context ctx = new Context(c, t, i, e.getKey());
-					ivs.put(calculateIv(ctx, e.getValue()), ctx);
+					ivs.put(calculateTag(ctx, e.getValue()), ctx);
 				}
 				w.erase();
 			}
diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
index 63cf1ba65a..04fffe4e90 100644
--- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
+++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java
@@ -32,14 +32,14 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 	}
 
 	public ConnectionWriter createConnectionWriter(OutputStream out,
-			long capacity, ConnectionContext ctx, byte[] encryptedIv) {
-		// Decrypt the IV
-		Cipher ivCipher = crypto.getIvCipher();
-		ErasableKey ivKey = crypto.deriveIvKey(ctx.getSecret(), true);
+			long capacity, ConnectionContext ctx, byte[] tag) {
+		// Decrypt the tag
+		Cipher tagCipher = crypto.getTagCipher();
+		ErasableKey tagKey = crypto.deriveTagKey(ctx.getSecret(), true);
 		byte[] iv;
 		try {
-			ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
-			iv = ivCipher.doFinal(encryptedIv);
+			tagCipher.init(Cipher.DECRYPT_MODE, tagKey);
+			iv = tagCipher.doFinal(tag);
 		} catch(BadPaddingException badCipher) {
 			throw new RuntimeException(badCipher);
 		} catch(IllegalBlockSizeException badCipher) {
@@ -47,8 +47,8 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 		} catch(InvalidKeyException badKey) {
 			throw new RuntimeException(badKey);
 		}
-		ivKey.erase();
-		// Validate the IV
+		tagKey.erase();
+		// Validate the tag
 		int index = ctx.getTransportIndex().getInt();
 		long connection = ctx.getConnectionNumber();
 		if(!IvEncoder.validateIv(iv, index, connection))
@@ -60,7 +60,7 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 			long capacity, boolean initiator, ConnectionContext ctx) {
 		// Derive the keys and erase the secret
 		byte[] secret = ctx.getSecret();
-		ErasableKey ivKey = crypto.deriveIvKey(secret, initiator);
+		ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
 		ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
 		ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
 		ByteUtils.erase(secret);
@@ -68,10 +68,10 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
 		int index = ctx.getTransportIndex().getInt();
 		long connection = ctx.getConnectionNumber();
 		byte[] iv = IvEncoder.encodeIv(index, connection);
-		Cipher ivCipher = crypto.getIvCipher();
+		Cipher tagCipher = crypto.getTagCipher();
 		Cipher frameCipher = crypto.getFrameCipher();
 		ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
-				capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
+				capacity, iv, tagCipher, frameCipher, tagKey, frameKey);
 		// Create the writer
 		Mac mac = crypto.getMac();
 		return new ConnectionWriterImpl(encrypter, mac, macKey);
diff --git a/components/net/sf/briar/transport/IvEncoder.java b/components/net/sf/briar/transport/IvEncoder.java
index fdb6ea1979..73fd0aea37 100644
--- a/components/net/sf/briar/transport/IvEncoder.java
+++ b/components/net/sf/briar/transport/IvEncoder.java
@@ -1,12 +1,12 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import net.sf.briar.util.ByteUtils;
 
 class IvEncoder {
 
 	static byte[] encodeIv(int index, long connection) {
-		byte[] iv = new byte[IV_LENGTH];
+		byte[] iv = new byte[TAG_LENGTH];
 		// Encode the transport index as an unsigned 16-bit integer
 		ByteUtils.writeUint16(index, iv, 4);
 		// Encode the connection number as an unsigned 32-bit integer
@@ -15,13 +15,13 @@ class IvEncoder {
 	}
 
 	static void updateIv(byte[] iv, long frame) {
-		if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
+		if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
 		// Encode the frame number as an unsigned 32-bit integer
 		ByteUtils.writeUint32(frame, iv, 10);
 	}
 
 	static boolean validateIv(byte[] iv, int index, long connection) {
-		if(iv.length != IV_LENGTH) return false;
+		if(iv.length != TAG_LENGTH) return false;
 		// Check that the reserved bits are all zero
 		for(int i = 0; i < 3; i++) if(iv[i] != 0) return false;
 		for(int i = 10; i < iv.length; i++) if(iv[i] != 0) return false;
@@ -34,12 +34,12 @@ class IvEncoder {
 	}
 
 	static int getTransportIndex(byte[] iv) {
-		if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
+		if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
 		return ByteUtils.readUint16(iv, 4);
 	}
 
 	static long getConnectionNumber(byte[] iv) {
-		if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
+		if(iv.length != TAG_LENGTH) throw new IllegalArgumentException();
 		return ByteUtils.readUint32(iv, 6);
 	}
 }
diff --git a/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java b/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java
index 280f865b41..da49fc6aec 100644
--- a/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java
+++ b/components/net/sf/briar/transport/batch/BatchConnectionFactoryImpl.java
@@ -35,9 +35,9 @@ class BatchConnectionFactoryImpl implements BatchConnectionFactory {
 	}
 
 	public void createIncomingConnection(ConnectionContext ctx,
-			BatchTransportReader r, byte[] encryptedIv) {
+			BatchTransportReader r, byte[] tag) {
 		final IncomingBatchConnection conn = new IncomingBatchConnection(
-				connReaderFactory, db, protoReaderFactory, ctx, r, encryptedIv);
+				connReaderFactory, db, protoReaderFactory, ctx, r, tag);
 		Runnable read = new Runnable() {
 			public void run() {
 				conn.read();
diff --git a/components/net/sf/briar/transport/batch/IncomingBatchConnection.java b/components/net/sf/briar/transport/batch/IncomingBatchConnection.java
index 4440edacd0..e7a0b3686b 100644
--- a/components/net/sf/briar/transport/batch/IncomingBatchConnection.java
+++ b/components/net/sf/briar/transport/batch/IncomingBatchConnection.java
@@ -29,24 +29,23 @@ class IncomingBatchConnection {
 	private final ProtocolReaderFactory protoFactory;
 	private final ConnectionContext ctx;
 	private final BatchTransportReader reader;
-	private final byte[] encryptedIv;
+	private final byte[] tag;
 
 	IncomingBatchConnection(ConnectionReaderFactory connFactory,
 			DatabaseComponent db, ProtocolReaderFactory protoFactory,
-			ConnectionContext ctx, BatchTransportReader reader,
-			byte[] encryptedIv) {
+			ConnectionContext ctx, BatchTransportReader reader, byte[] tag) {
 		this.connFactory = connFactory;
 		this.db = db;
 		this.protoFactory = protoFactory;
 		this.ctx = ctx;
 		this.reader = reader;
-		this.encryptedIv = encryptedIv;
+		this.tag = tag;
 	}
 
 	void read() {
 		try {
 			ConnectionReader conn = connFactory.createConnectionReader(
-					reader.getInputStream(), ctx, encryptedIv);
+					reader.getInputStream(), ctx, tag);
 			ProtocolReader proto = protoFactory.createProtocolReader(
 					conn.getInputStream());
 			ContactId c = ctx.getContactId();
diff --git a/components/net/sf/briar/transport/stream/IncomingStreamConnection.java b/components/net/sf/briar/transport/stream/IncomingStreamConnection.java
index 994693d0b7..405001957e 100644
--- a/components/net/sf/briar/transport/stream/IncomingStreamConnection.java
+++ b/components/net/sf/briar/transport/stream/IncomingStreamConnection.java
@@ -16,31 +16,31 @@ import net.sf.briar.api.transport.StreamTransportConnection;
 class IncomingStreamConnection extends StreamConnection {
 
 	private final ConnectionContext ctx;
-	private final byte[] encryptedIv;
+	private final byte[] tag;
 
 	IncomingStreamConnection(ConnectionReaderFactory connReaderFactory,
 			ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
 			ProtocolReaderFactory protoReaderFactory,
 			ProtocolWriterFactory protoWriterFactory,
 			ConnectionContext ctx, StreamTransportConnection connection,
-			byte[] encryptedIv) {
+			byte[] tag) {
 		super(connReaderFactory, connWriterFactory, db, protoReaderFactory,
 				protoWriterFactory, ctx.getContactId(), connection);
 		this.ctx = ctx;
-		this.encryptedIv = encryptedIv;
+		this.tag = tag;
 	}
 
 	@Override
 	protected ConnectionReader createConnectionReader() throws DbException,
 	IOException {
 		return connReaderFactory.createConnectionReader(
-				connection.getInputStream(), ctx, encryptedIv);
+				connection.getInputStream(), ctx, tag);
 	}
 
 	@Override
 	protected ConnectionWriter createConnectionWriter() throws DbException,
 	IOException {
 		return connWriterFactory.createConnectionWriter(
-				connection.getOutputStream(), Long.MAX_VALUE, ctx, encryptedIv);
+				connection.getOutputStream(), Long.MAX_VALUE, ctx, tag);
 	}
 }
diff --git a/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java b/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java
index 514a702302..b5651a0911 100644
--- a/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java
+++ b/components/net/sf/briar/transport/stream/StreamConnectionFactoryImpl.java
@@ -34,10 +34,10 @@ class StreamConnectionFactoryImpl implements StreamConnectionFactory {
 	}
 
 	public void createIncomingConnection(ConnectionContext ctx,
-			StreamTransportConnection s, byte[] encryptedIv) {
+			StreamTransportConnection s, byte[] tag) {
 		final StreamConnection conn = new IncomingStreamConnection(
 				connReaderFactory, connWriterFactory, db, protoReaderFactory,
-				protoWriterFactory, ctx, s, encryptedIv);
+				protoWriterFactory, ctx, s, tag);
 		Runnable write = new Runnable() {
 			public void run() {
 				conn.write();
diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java
index 1ed4eb0fb7..1aba7e21cb 100644
--- a/test/net/sf/briar/ProtocolIntegrationTest.java
+++ b/test/net/sf/briar/ProtocolIntegrationTest.java
@@ -52,6 +52,7 @@ import net.sf.briar.api.transport.ConnectionReader;
 import net.sf.briar.api.transport.ConnectionReaderFactory;
 import net.sf.briar.api.transport.ConnectionWriter;
 import net.sf.briar.api.transport.ConnectionWriterFactory;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import net.sf.briar.crypto.CryptoModule;
 import net.sf.briar.db.DatabaseModule;
 import net.sf.briar.lifecycle.LifecycleModule;
@@ -206,13 +207,13 @@ public class ProtocolIntegrationTest extends TestCase {
 
 	private void read(byte[] connectionData) throws Exception {
 		InputStream in = new ByteArrayInputStream(connectionData);
-		byte[] encryptedIv = new byte[16];
-		assertEquals(16, in.read(encryptedIv, 0, 16));
+		byte[] tag = new byte[TAG_LENGTH];
+		assertEquals(TAG_LENGTH, in.read(tag, 0, TAG_LENGTH));
 		ConnectionContext ctx =
 			connectionContextFactory.createConnectionContext(contactId,
 					transportIndex, connection, Arrays.clone(secret));
 		ConnectionReader r = connectionReaderFactory.createConnectionReader(in,
-				ctx, encryptedIv);
+				ctx, tag);
 		in = r.getInputStream();
 		ProtocolReader protocolReader =
 			protocolReaderFactory.createProtocolReader(in);
diff --git a/test/net/sf/briar/crypto/KeyDerivationTest.java b/test/net/sf/briar/crypto/KeyDerivationTest.java
index 2ca2ad7320..22bb592296 100644
--- a/test/net/sf/briar/crypto/KeyDerivationTest.java
+++ b/test/net/sf/briar/crypto/KeyDerivationTest.java
@@ -29,8 +29,8 @@ public class KeyDerivationTest extends TestCase {
 		List<ErasableKey> keys = new ArrayList<ErasableKey>();
 		keys.add(crypto.deriveFrameKey(secret, true));
 		keys.add(crypto.deriveFrameKey(secret, false));
-		keys.add(crypto.deriveIvKey(secret, true));
-		keys.add(crypto.deriveIvKey(secret, false));
+		keys.add(crypto.deriveTagKey(secret, true));
+		keys.add(crypto.deriveTagKey(secret, false));
 		keys.add(crypto.deriveMacKey(secret, true));
 		keys.add(crypto.deriveMacKey(secret, false));
 		for(int i = 0; i < 6; i++) {
diff --git a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
index b34e549408..1289790de1 100644
--- a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 
 import java.io.ByteArrayInputStream;
@@ -25,8 +25,8 @@ public class ConnectionDecrypterImplTest extends TestCase {
 
 	private static final int MAC_LENGTH = 32;
 
-	private final Cipher ivCipher, frameCipher;
-	private final ErasableKey ivKey, frameKey;
+	private final Cipher tagCipher, frameCipher;
+	private final ErasableKey tagKey, frameKey;
 	private final TransportIndex transportIndex = new TransportIndex(13);
 	private final long connection = 12345L;
 
@@ -34,9 +34,9 @@ public class ConnectionDecrypterImplTest extends TestCase {
 		super();
 		Injector i = Guice.createInjector(new CryptoModule());
 		CryptoComponent crypto = i.getInstance(CryptoComponent.class);
-		ivCipher = crypto.getIvCipher();
+		tagCipher = crypto.getTagCipher();
 		frameCipher = crypto.getFrameCipher();
-		ivKey = crypto.generateTestKey();
+		tagKey = crypto.generateTestKey();
 		frameKey = crypto.generateTestKey();
 	}
 
@@ -53,9 +53,9 @@ public class ConnectionDecrypterImplTest extends TestCase {
 	private void testDecryption(boolean initiator) throws Exception {
 		// Calculate the plaintext and ciphertext for the IV
 		byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
-		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
-		byte[] encryptedIv  = ivCipher.doFinal(iv);
-		assertEquals(IV_LENGTH, encryptedIv.length);
+		tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
+		byte[] tag  = tagCipher.doFinal(iv);
+		assertEquals(TAG_LENGTH, tag.length);
 		// Calculate the expected plaintext for the first frame
 		byte[] ciphertext = new byte[123];
 		byte[] ciphertextMac = new byte[MAC_LENGTH];
diff --git a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
index ecbf2cbf5b..1af4902cfd 100644
--- a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 
 import java.io.ByteArrayOutputStream;
@@ -23,8 +23,8 @@ public class ConnectionEncrypterImplTest extends TestCase {
 
 	private static final int MAC_LENGTH = 32;
 
-	private final Cipher ivCipher, frameCipher;
-	private final ErasableKey ivKey, frameKey;
+	private final Cipher tagCipher, frameCipher;
+	private final ErasableKey tagKey, frameKey;
 	private final TransportIndex transportIndex = new TransportIndex(13);
 	private final long connection = 12345L;
 
@@ -32,9 +32,9 @@ public class ConnectionEncrypterImplTest extends TestCase {
 		super();
 		Injector i = Guice.createInjector(new CryptoModule());
 		CryptoComponent crypto = i.getInstance(CryptoComponent.class);
-		ivCipher = crypto.getIvCipher();
+		tagCipher = crypto.getTagCipher();
 		frameCipher = crypto.getFrameCipher();
-		ivKey = crypto.generateTestKey();
+		tagKey = crypto.generateTestKey();
 		frameKey = crypto.generateTestKey();
 	}
 
@@ -51,9 +51,9 @@ public class ConnectionEncrypterImplTest extends TestCase {
 	private void testEncryption(boolean initiator) throws Exception {
 		// Calculate the expected ciphertext for the IV
 		byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
-		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
-		byte[] encryptedIv = ivCipher.doFinal(iv);
-		assertEquals(IV_LENGTH, encryptedIv.length);
+		tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
+		byte[] tag = tagCipher.doFinal(iv);
+		assertEquals(TAG_LENGTH, tag.length);
 		// Calculate the expected ciphertext for the first frame
 		byte[] plaintext = new byte[123];
 		byte[] plaintextMac = new byte[MAC_LENGTH];
@@ -76,7 +76,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
 				offset);
 		// Concatenate the ciphertexts
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		out.write(encryptedIv);
+		out.write(tag);
 		out.write(ciphertext);
 		out.write(ciphertext1);
 		byte[] expected = out.toByteArray();
@@ -84,7 +84,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
 		out.reset();
 		iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
 		ConnectionEncrypter e = new ConnectionEncrypterImpl(out, Long.MAX_VALUE,
-				iv, ivCipher, frameCipher, ivKey, frameKey);
+				iv, tagCipher, frameCipher, tagKey, 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 3883033dfb..2198b6402c 100644
--- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
+++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -83,7 +83,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		assertNull(c.acceptConnection(transportId, new byte[IV_LENGTH]));
+		assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
 		context.assertIsSatisfied();
 	}
 
@@ -111,18 +111,18 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
-		// The IV should not be expected by the wrong transport
+		byte[] tag = calculateTag();
+		// The tag should not be expected by the wrong transport
 		TransportId wrong = new TransportId(TestUtils.getRandomId());
-		assertNull(c.acceptConnection(wrong, encryptedIv));
-		// The IV should be expected by the right transport
-		ConnectionContext ctx = c.acceptConnection(transportId, encryptedIv);
+		assertNull(c.acceptConnection(wrong, tag));
+		// The tag should be expected by the right transport
+		ConnectionContext ctx = c.acceptConnection(transportId, tag);
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -152,15 +152,15 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Ensure the recogniser is initialised
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, new byte[IV_LENGTH]));
+		assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
 		assertTrue(c.isInitialised());
 		// Remove the contact
 		c.eventOccurred(new ContactRemovedEvent(contactId));
-		// The IV should not be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should not be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		context.assertIsSatisfied();
 	}
 
@@ -179,12 +179,12 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Remove the contact
 		c.eventOccurred(new ContactRemovedEvent(contactId));
-		// The IV should not be expected
+		// The tag should not be expected
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		assertNull(c.acceptConnection(transportId, tag));
 		assertTrue(c.isInitialised());
 		context.assertIsSatisfied();
 	}
@@ -216,21 +216,21 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
-		// The IV should not be expected
+		byte[] tag = calculateTag();
+		// The tag should not be expected
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		assertNull(c.acceptConnection(transportId, tag));
 		assertTrue(c.isInitialised());
 		// Add the transport
 		c.eventOccurred(new TransportAddedEvent(transportId));
-		// The IV should be expected
-		ConnectionContext ctx = c.acceptConnection(transportId, encryptedIv);
+		// The tag should be expected
+		ConnectionContext ctx = c.acceptConnection(transportId, tag);
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -264,19 +264,19 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Add the transport
 		c.eventOccurred(new TransportAddedEvent(transportId));
-		// The IV should be expected
+		// The tag should be expected
 		assertFalse(c.isInitialised());
-		ConnectionContext ctx = c.acceptConnection(transportId, encryptedIv);
+		ConnectionContext ctx = c.acceptConnection(transportId, tag);
 		assertTrue(c.isInitialised());
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -311,22 +311,22 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
-		// The IV should not be expected
+		byte[] tag = calculateTag();
+		// The tag should not be expected
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		assertNull(c.acceptConnection(transportId, tag));
 		assertTrue(c.isInitialised());
 		// Update the contact
 		c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
 				remoteTransports));
-		// The IV should be expected
-		ConnectionContext ctx = c.acceptConnection(transportId, encryptedIv);
+		// The tag should be expected
+		ConnectionContext ctx = c.acceptConnection(transportId, tag);
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -360,20 +360,20 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Update the contact
 		c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
 				remoteTransports));
-		// The IV should be expected
+		// The tag should be expected
 		assertFalse(c.isInitialised());
-		ConnectionContext ctx = c.acceptConnection(transportId, encryptedIv);
+		ConnectionContext ctx = c.acceptConnection(transportId, tag);
 		assertTrue(c.isInitialised());
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -403,16 +403,16 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Ensure the recogniser is initialised
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, new byte[IV_LENGTH]));
+		assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
 		assertTrue(c.isInitialised());
 		// Update the contact
 		c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
 				Collections.<Transport>emptyList()));
-		// The IV should not be expected
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		// The tag should not be expected
+		assertNull(c.acceptConnection(transportId, tag));
 		context.assertIsSatisfied();
 	}
 
@@ -433,13 +433,13 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Update the contact
 		c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
 				Collections.<Transport>emptyList()));
-		// The IV should not be expected
+		// The tag should not be expected
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		assertNull(c.acceptConnection(transportId, tag));
 		assertTrue(c.isInitialised());
 		context.assertIsSatisfied();
 	}
@@ -499,24 +499,24 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Ensure the recogniser is initialised
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, new byte[IV_LENGTH]));
+		assertNull(c.acceptConnection(transportId, new byte[TAG_LENGTH]));
 		assertTrue(c.isInitialised());
 		// Update the contact
 		c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
 				remoteTransports1));
-		// The IV should not be expected by the old transport
-		assertNull(c.acceptConnection(transportId, encryptedIv));
-		// The IV should be expected by the new transport
-		ConnectionContext ctx = c.acceptConnection(transportId1, encryptedIv);
+		// The tag should not be expected by the old transport
+		assertNull(c.acceptConnection(transportId, tag));
+		// The tag should be expected by the new transport
+		ConnectionContext ctx = c.acceptConnection(transportId1, tag);
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId1, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId1, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -576,22 +576,22 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		Executor executor = new ImmediateExecutor();
 		ConnectionRecogniserImpl c = new ConnectionRecogniserImpl(crypto, db,
 				executor);
-		byte[] encryptedIv = calculateIv();
+		byte[] tag = calculateTag();
 		// Update the contact
 		c.eventOccurred(new RemoteTransportsUpdatedEvent(contactId,
 				remoteTransports1));
-		// The IV should not be expected by the old transport
+		// The tag should not be expected by the old transport
 		assertFalse(c.isInitialised());
-		assertNull(c.acceptConnection(transportId, encryptedIv));
+		assertNull(c.acceptConnection(transportId, tag));
 		assertTrue(c.isInitialised());
-		// The IV should be expected by the new transport
-		ConnectionContext ctx = c.acceptConnection(transportId1, encryptedIv);
+		// The tag should be expected by the new transport
+		ConnectionContext ctx = c.acceptConnection(transportId1, tag);
 		assertNotNull(ctx);
 		assertEquals(contactId, ctx.getContactId());
 		assertEquals(remoteIndex, ctx.getTransportIndex());
 		assertEquals(3, ctx.getConnectionNumber());
-		// The IV should no longer be expected
-		assertNull(c.acceptConnection(transportId1, encryptedIv));
+		// The tag should no longer be expected
+		assertNull(c.acceptConnection(transportId1, tag));
 		// The window should have advanced
 		Map<Long, byte[]> unseen = window.getUnseen();
 		assertEquals(19, unseen.size());
@@ -608,17 +608,17 @@ public class ConnectionRecogniserImplTest extends TestCase {
 		};
 	}
 
-	private byte[] calculateIv() throws Exception {
+	private byte[] calculateTag() throws Exception {
 		// Calculate the shared secret for connection number 3
 		byte[] secret = inSecret;
 		for(int i = 0; i < 4; i++) {
 			secret = crypto.deriveNextSecret(secret, remoteIndex.getInt(), i);
 		}
-		// Calculate the expected IV for connection number 3
-		ErasableKey ivKey = crypto.deriveIvKey(secret, true);
-		Cipher ivCipher = crypto.getIvCipher();
-		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
+		// Calculate the expected tag for connection number 3
+		ErasableKey tagKey = crypto.deriveTagKey(secret, true);
+		Cipher tagCipher = crypto.getTagCipher();
+		tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
 		byte[] iv = IvEncoder.encodeIv(remoteIndex.getInt(), 3);
-		return ivCipher.doFinal(iv);
+		return tagCipher.doFinal(iv);
 	}
 }
diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java
index f9d23a6609..b15428f3ea 100644
--- a/test/net/sf/briar/transport/FrameReadWriteTest.java
+++ b/test/net/sf/briar/transport/FrameReadWriteTest.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
 
 import java.io.ByteArrayInputStream;
@@ -28,10 +28,10 @@ import com.google.inject.Injector;
 public class FrameReadWriteTest extends TestCase {
 
 	private final CryptoComponent crypto;
-	private final Cipher ivCipher, frameCipher;
+	private final Cipher tagCipher, frameCipher;
 	private final Random random;
 	private final byte[] outSecret;
-	private final ErasableKey ivKey, frameKey, macKey;
+	private final ErasableKey tagKey, frameKey, macKey;
 	private final Mac mac;
 	private final TransportIndex transportIndex = new TransportIndex(13);
 	private final long connection = 12345L;
@@ -40,13 +40,13 @@ public class FrameReadWriteTest extends TestCase {
 		super();
 		Injector i = Guice.createInjector(new CryptoModule());
 		crypto = i.getInstance(CryptoComponent.class);
-		ivCipher = crypto.getIvCipher();
+		tagCipher = crypto.getTagCipher();
 		frameCipher = crypto.getFrameCipher();
 		random = new Random();
 		// Since we're sending frames to ourselves, we only need outgoing keys
 		outSecret = new byte[32];
 		random.nextBytes(outSecret);
-		ivKey = crypto.deriveIvKey(outSecret, true);
+		tagKey = crypto.deriveTagKey(outSecret, true);
 		frameKey = crypto.deriveFrameKey(outSecret, true);
 		macKey = crypto.deriveMacKey(outSecret, true);
 		mac = crypto.getMac();
@@ -65,9 +65,9 @@ public class FrameReadWriteTest extends TestCase {
 	private void testWriteAndRead(boolean initiator) throws Exception {
 		// Create and encrypt the IV
 		byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
-		ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
-		byte[] encryptedIv = ivCipher.doFinal(iv);
-		assertEquals(IV_LENGTH, encryptedIv.length);
+		tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
+		byte[] tag = tagCipher.doFinal(iv);
+		assertEquals(TAG_LENGTH, tag.length);
 		// Generate two random frames
 		byte[] frame = new byte[12345];
 		random.nextBytes(frame);
@@ -75,12 +75,12 @@ public class FrameReadWriteTest extends TestCase {
 		random.nextBytes(frame1);
 		// Copy the keys - the copies will be erased
 		ErasableKey frameCopy = frameKey.copy();
-		ErasableKey ivCopy = ivKey.copy();
+		ErasableKey tagCopy = tagKey.copy();
 		ErasableKey macCopy = macKey.copy();
 		// Write the frames
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
 		ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
-				Long.MAX_VALUE, iv, ivCipher, frameCipher, ivCopy, frameCopy);
+				Long.MAX_VALUE, iv, tagCipher, frameCipher, tagCopy, frameCopy);
 		ConnectionWriter writer = new ConnectionWriterImpl(encrypter, mac,
 				macCopy);
 		OutputStream out1 = writer.getOutputStream();
@@ -90,12 +90,12 @@ public class FrameReadWriteTest extends TestCase {
 		out1.flush();
 		// Read the IV back
 		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
-		byte[] recoveredEncryptedIv = new byte[IV_LENGTH];
-		assertEquals(IV_LENGTH, in.read(recoveredEncryptedIv));
-		assertArrayEquals(encryptedIv, recoveredEncryptedIv);
+		byte[] recoveredTag = new byte[TAG_LENGTH];
+		assertEquals(TAG_LENGTH, in.read(recoveredTag));
+		assertArrayEquals(tag, recoveredTag);
 		// Decrypt the IV
-		ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
-		byte[] recoveredIv = ivCipher.doFinal(recoveredEncryptedIv);
+		tagCipher.init(Cipher.DECRYPT_MODE, tagKey);
+		byte[] recoveredIv = tagCipher.doFinal(recoveredTag);
 		iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
 		assertArrayEquals(iv, recoveredIv);
 		// Read the frames back
diff --git a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
index 45ce4c504f..1e7ff71255 100644
--- a/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
+++ b/test/net/sf/briar/transport/batch/BatchConnectionReadWriteTest.java
@@ -1,6 +1,6 @@
 package net.sf.briar.transport.batch;
 
-import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
+import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -170,11 +170,11 @@ public class BatchConnectionReadWriteTest extends TestCase {
 		// Create a connection recogniser and recognise the connection
 		ByteArrayInputStream in = new ByteArrayInputStream(b);
 		ConnectionRecogniser rec = bob.getInstance(ConnectionRecogniser.class);
-		byte[] encryptedIv = new byte[IV_LENGTH];
-		int read = in.read(encryptedIv);
-		assertEquals(encryptedIv.length, read);
+		byte[] tag = new byte[TAG_LENGTH];
+		int read = in.read(tag);
+		assertEquals(tag.length, read);
 		TestCallback callback = new TestCallback();
-		rec.acceptConnection(transportId, encryptedIv, callback);
+		rec.acceptConnection(transportId, tag, callback);
 		callback.latch.await();
 		ConnectionContext ctx = callback.ctx;
 		assertNotNull(ctx);
@@ -187,7 +187,7 @@ public class BatchConnectionReadWriteTest extends TestCase {
 			bob.getInstance(ProtocolReaderFactory.class);
 		BatchTransportReader reader = new TestBatchTransportReader(in);
 		IncomingBatchConnection batchIn = new IncomingBatchConnection(
-				connFactory, db, protoFactory, ctx, reader, encryptedIv);
+				connFactory, db, protoFactory, ctx, reader, tag);
 		// No messages should have been added yet
 		assertFalse(listener.messagesAdded);
 		// Read whatever needs to be read
-- 
GitLab