From 14d5e6fe642739dc804bc5e870cc232c662e5f20 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Fri, 2 Dec 2011 12:57:39 +0000 Subject: [PATCH] Replaced encrypted IVs with pseudo-random tags. --- .../sf/briar/crypto/CryptoComponentImpl.java | 10 ++-- .../transport/ConnectionDecrypterImpl.java | 11 ++-- .../transport/ConnectionEncrypterImpl.java | 20 ++----- .../ConnectionReaderFactoryImpl.java | 28 ++-------- .../transport/ConnectionRecogniserImpl.java | 21 ++------ .../ConnectionWriterFactoryImpl.java | 26 ++------- .../net/sf/briar/transport/IvEncoder.java | 40 +++----------- .../net/sf/briar/transport/TagEncoder.java | 54 +++++++++++++++++++ .../ConnectionDecrypterImplTest.java | 23 +++----- .../ConnectionEncrypterImplTest.java | 17 ++---- .../ConnectionRecogniserImplTest.java | 4 +- .../briar/transport/FrameReadWriteTest.java | 24 +++------ 12 files changed, 104 insertions(+), 174 deletions(-) create mode 100644 components/net/sf/briar/transport/TagEncoder.java diff --git a/components/net/sf/briar/crypto/CryptoComponentImpl.java b/components/net/sf/briar/crypto/CryptoComponentImpl.java index 34eeea8bd8..b1ae497099 100644 --- a/components/net/sf/briar/crypto/CryptoComponentImpl.java +++ b/components/net/sf/briar/crypto/CryptoComponentImpl.java @@ -27,13 +27,11 @@ class CryptoComponentImpl implements CryptoComponent { private static final String DIGEST_ALGO = "SHA-256"; private static final String KEY_PAIR_ALGO = "ECDSA"; private static final int KEY_PAIR_BITS = 256; - private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding"; + private static final String 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 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"; private static final int KEY_DERIVATION_IV_BYTES = 16; // 128 bits // Labels for key derivation, null-terminated @@ -104,7 +102,7 @@ class CryptoComponentImpl implements CryptoComponent { assert ivBytes[ivBytes.length - 1] == 0; IvParameterSpec iv = new IvParameterSpec(ivBytes); try { - Cipher cipher = Cipher.getInstance(KEY_DERIVATION_ALGO, PROVIDER); + Cipher cipher = Cipher.getInstance(CIPHER_ALGO, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, key, iv); byte[] output = cipher.doFinal(KEY_DERIVATION_INPUT); assert output.length == SECRET_KEY_BYTES; @@ -137,7 +135,7 @@ class CryptoComponentImpl implements CryptoComponent { public Cipher getFrameCipher() { try { - return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER); + return Cipher.getInstance(CIPHER_ALGO, PROVIDER); } catch(GeneralSecurityException e) { throw new RuntimeException(e); } @@ -178,7 +176,7 @@ class CryptoComponentImpl implements CryptoComponent { public Cipher getTagCipher() { try { - return Cipher.getInstance(TAG_CIPHER_ALGO, PROVIDER); + return Cipher.getInstance(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 7eb56ab101..ac9557c88c 100644 --- a/components/net/sf/briar/transport/ConnectionDecrypterImpl.java +++ b/components/net/sf/briar/transport/ConnectionDecrypterImpl.java @@ -1,6 +1,5 @@ package net.sf.briar.transport; -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; @@ -13,10 +12,11 @@ import java.security.InvalidKeyException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; -import net.sf.briar.api.crypto.ErasableKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.IvParameterSpec; +import net.sf.briar.api.crypto.ErasableKey; + class ConnectionDecrypterImpl extends FilterInputStream implements ConnectionDecrypter { @@ -28,14 +28,13 @@ implements ConnectionDecrypter { private long frame = 0L; private boolean betweenFrames = true; - ConnectionDecrypterImpl(InputStream in, byte[] iv, Cipher frameCipher, + ConnectionDecrypterImpl(InputStream in, Cipher frameCipher, ErasableKey frameKey) { super(in); - if(iv.length != TAG_LENGTH) throw new IllegalArgumentException(); - this.iv = iv; this.frameCipher = frameCipher; this.frameKey = frameKey; - buf = new byte[TAG_LENGTH]; + iv = IvEncoder.encodeIv(0, frameCipher.getBlockSize()); + buf = new byte[frameCipher.getBlockSize()]; } public InputStream getInputStream() { diff --git a/components/net/sf/briar/transport/ConnectionEncrypterImpl.java b/components/net/sf/briar/transport/ConnectionEncrypterImpl.java index 0eb7ff5111..54446b09e2 100644 --- a/components/net/sf/briar/transport/ConnectionEncrypterImpl.java +++ b/components/net/sf/briar/transport/ConnectionEncrypterImpl.java @@ -25,27 +25,17 @@ implements ConnectionEncrypter { private long capacity, frame = 0L; private boolean tagWritten = false, betweenFrames = false; - ConnectionEncrypterImpl(OutputStream out, long capacity, byte[] iv, - Cipher tagCipher, Cipher frameCipher, ErasableKey tagKey, - ErasableKey frameKey) { + ConnectionEncrypterImpl(OutputStream out, long capacity, Cipher tagCipher, + Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey) { super(out); this.capacity = capacity; - this.iv = iv; this.frameCipher = frameCipher; this.frameKey = frameKey; + iv = IvEncoder.encodeIv(0, frameCipher.getBlockSize()); // Encrypt the tag - try { - tagCipher.init(Cipher.ENCRYPT_MODE, tagKey); - tag = tagCipher.doFinal(iv); - } catch(BadPaddingException badCipher) { - throw new IllegalArgumentException(badCipher); - } catch(IllegalBlockSizeException badCipher) { - throw new IllegalArgumentException(badCipher); - } catch(InvalidKeyException badKey) { - throw new IllegalArgumentException(badKey); - } - if(tag.length != TAG_LENGTH) throw new IllegalArgumentException(); + tag = TagEncoder.encodeTag(0, tagCipher, tagKey); tagKey.erase(); + if(tag.length != TAG_LENGTH) throw new IllegalArgumentException(); } public OutputStream getOutputStream() { diff --git a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java index 6ad7b806f8..837ce54087 100644 --- a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java @@ -1,11 +1,8 @@ package net.sf.briar.transport; import java.io.InputStream; -import java.security.InvalidKeyException; -import javax.crypto.BadPaddingException; import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; import javax.crypto.Mac; import net.sf.briar.api.crypto.CryptoComponent; @@ -28,26 +25,12 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { public ConnectionReader createConnectionReader(InputStream in, ConnectionContext ctx, byte[] tag) { - // Decrypt the tag + // Validate the tag Cipher tagCipher = crypto.getTagCipher(); ErasableKey tagKey = crypto.deriveTagKey(ctx.getSecret(), true); - byte[] iv; - try { - tagCipher.init(Cipher.DECRYPT_MODE, tagKey); - iv = tagCipher.doFinal(tag); - } catch(BadPaddingException badCipher) { - throw new IllegalArgumentException(badCipher); - } catch(IllegalBlockSizeException badCipher) { - throw new IllegalArgumentException(badCipher); - } catch(InvalidKeyException badKey) { - throw new IllegalArgumentException(badKey); - } + boolean valid = TagEncoder.validateTag(tag, 0, tagCipher, tagKey); tagKey.erase(); - // Validate the tag - int index = ctx.getTransportIndex().getInt(); - long connection = ctx.getConnectionNumber(); - if(!IvEncoder.validateIv(iv, index, connection)) - throw new IllegalArgumentException(); + if(!valid) throw new IllegalArgumentException(); return createConnectionReader(in, true, ctx); } @@ -64,11 +47,8 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { ErasableKey macKey = crypto.deriveMacKey(secret, initiator); ByteUtils.erase(secret); // Create the decrypter - int index = ctx.getTransportIndex().getInt(); - long connection = ctx.getConnectionNumber(); - byte[] iv = IvEncoder.encodeIv(index, connection); Cipher frameCipher = crypto.getFrameCipher(); - ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv, + ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, frameCipher, frameKey); // Create the reader Mac mac = crypto.getMac(); diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java index e365d6a99c..08c2ed3de2 100644 --- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java +++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java @@ -2,7 +2,6 @@ package net.sf.briar.transport; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; -import java.security.InvalidKeyException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -15,9 +14,7 @@ import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.Logger; -import javax.crypto.BadPaddingException; import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; import net.sf.briar.api.Bytes; import net.sf.briar.api.ContactId; @@ -103,22 +100,10 @@ DatabaseListener { // Locking: this private Bytes calculateTag(Context ctx, byte[] secret) { - byte[] iv = IvEncoder.encodeIv(ctx.transportIndex.getInt(), - ctx.connection); ErasableKey tagKey = crypto.deriveTagKey(secret, true); - try { - 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) { - throw new RuntimeException(badCipher); - } catch(InvalidKeyException badKey) { - throw new RuntimeException(badKey); - } finally { - tagKey.erase(); - } + byte[] tag = TagEncoder.encodeTag(0, tagCipher, tagKey); + tagKey.erase(); + return new Bytes(tag); } public void acceptConnection(final TransportId t, final byte[] tag, diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java index 04fffe4e90..694db4ae77 100644 --- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java @@ -1,11 +1,8 @@ package net.sf.briar.transport; import java.io.OutputStream; -import java.security.InvalidKeyException; -import javax.crypto.BadPaddingException; import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; import javax.crypto.Mac; import net.sf.briar.api.crypto.CryptoComponent; @@ -36,23 +33,9 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { // Decrypt the tag Cipher tagCipher = crypto.getTagCipher(); ErasableKey tagKey = crypto.deriveTagKey(ctx.getSecret(), true); - byte[] iv; - try { - tagCipher.init(Cipher.DECRYPT_MODE, tagKey); - iv = tagCipher.doFinal(tag); - } catch(BadPaddingException badCipher) { - throw new RuntimeException(badCipher); - } catch(IllegalBlockSizeException badCipher) { - throw new RuntimeException(badCipher); - } catch(InvalidKeyException badKey) { - throw new RuntimeException(badKey); - } + boolean valid = TagEncoder.validateTag(tag, 0, tagCipher, tagKey); tagKey.erase(); - // Validate the tag - int index = ctx.getTransportIndex().getInt(); - long connection = ctx.getConnectionNumber(); - if(!IvEncoder.validateIv(iv, index, connection)) - throw new IllegalArgumentException(); + if(!valid) throw new IllegalArgumentException(); return createConnectionWriter(out, capacity, false, ctx); } @@ -65,13 +48,10 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { ErasableKey macKey = crypto.deriveMacKey(secret, initiator); ByteUtils.erase(secret); // Create the encrypter - int index = ctx.getTransportIndex().getInt(); - long connection = ctx.getConnectionNumber(); - byte[] iv = IvEncoder.encodeIv(index, connection); Cipher tagCipher = crypto.getTagCipher(); Cipher frameCipher = crypto.getFrameCipher(); ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out, - capacity, iv, tagCipher, frameCipher, tagKey, frameKey); + capacity, 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 73fd0aea37..8475f29d3e 100644 --- a/components/net/sf/briar/transport/IvEncoder.java +++ b/components/net/sf/briar/transport/IvEncoder.java @@ -1,45 +1,19 @@ package net.sf.briar.transport; -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[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 - ByteUtils.writeUint32(connection, iv, 6); + static byte[] encodeIv(long frame, int blockSize) { + if(frame > ByteUtils.MAX_32_BIT_UNSIGNED) + throw new IllegalArgumentException(); + byte[] iv = new byte[blockSize]; + updateIv(iv, frame); return iv; } static void updateIv(byte[] iv, long frame) { - 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 != 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; - // Check that the transport index matches - if(index != getTransportIndex(iv)) return false; - // Check that the connection number matches - if(connection != getConnectionNumber(iv)) return false; - // The IV is valid - return true; - } - - static int getTransportIndex(byte[] iv) { - if(iv.length != TAG_LENGTH) throw new IllegalArgumentException(); - return ByteUtils.readUint16(iv, 4); - } - - static long getConnectionNumber(byte[] iv) { - if(iv.length != TAG_LENGTH) throw new IllegalArgumentException(); - return ByteUtils.readUint32(iv, 6); + // Encode the frame number as a uint32, leaving 2 bytes for the counter + ByteUtils.writeUint32(frame, iv, iv.length - 6); } } diff --git a/components/net/sf/briar/transport/TagEncoder.java b/components/net/sf/briar/transport/TagEncoder.java new file mode 100644 index 0000000000..d74da3174c --- /dev/null +++ b/components/net/sf/briar/transport/TagEncoder.java @@ -0,0 +1,54 @@ +package net.sf.briar.transport; + +import java.security.GeneralSecurityException; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; + +import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.transport.TransportConstants; +import net.sf.briar.util.ByteUtils; + +class TagEncoder { + + static byte[] encodeTag(long frame, Cipher tagCipher, ErasableKey tagKey) { + if(frame > ByteUtils.MAX_32_BIT_UNSIGNED) + throw new IllegalArgumentException(); + // The plaintext is blank + byte[] plaintext = new byte[TransportConstants.TAG_LENGTH]; + // Encode the frame number as a uint32 at the end of the IV + byte[] iv = new byte[tagCipher.getBlockSize()]; + if(iv.length != plaintext.length) throw new IllegalArgumentException(); + ByteUtils.writeUint32(frame, iv, iv.length - 4); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + try { + tagCipher.init(Cipher.ENCRYPT_MODE, tagKey, ivSpec); + return tagCipher.doFinal(plaintext); + } catch(GeneralSecurityException e) { + // Unsuitable cipher or key + throw new IllegalArgumentException(e); + } + } + + static boolean validateTag(byte[] tag, long frame, Cipher tagCipher, + ErasableKey tagKey) { + if(tag.length != TransportConstants.TAG_LENGTH) return false; + // Encode the frame number as a uint32 at the end of the IV + byte[] iv = new byte[tagCipher.getBlockSize()]; + if(iv.length != tag.length) throw new IllegalArgumentException(); + ByteUtils.writeUint32(frame, iv, iv.length - 4); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + try { + tagCipher.init(Cipher.DECRYPT_MODE, tagKey, ivSpec); + byte[] plaintext = tagCipher.doFinal(tag); + // The plaintext should be blank + for(int i = 0; i < plaintext.length; i++) { + if(plaintext[i] != 0) return false; + } + return true; + } catch(GeneralSecurityException e) { + // Unsuitable cipher or key + throw new IllegalArgumentException(e); + } + } +} diff --git a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java index 1289790de1..e8a13dc3f3 100644 --- a/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java +++ b/test/net/sf/briar/transport/ConnectionDecrypterImplTest.java @@ -1,18 +1,16 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import static org.junit.Assert.assertArrayEquals; import java.io.ByteArrayInputStream; import javax.crypto.Cipher; -import net.sf.briar.api.crypto.ErasableKey; import javax.crypto.spec.IvParameterSpec; import junit.framework.TestCase; import net.sf.briar.TestUtils; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.protocol.TransportIndex; +import net.sf.briar.api.crypto.ErasableKey; import net.sf.briar.crypto.CryptoModule; import org.apache.commons.io.output.ByteArrayOutputStream; @@ -25,18 +23,14 @@ public class ConnectionDecrypterImplTest extends TestCase { private static final int MAC_LENGTH = 32; - private final Cipher tagCipher, frameCipher; - private final ErasableKey tagKey, frameKey; - private final TransportIndex transportIndex = new TransportIndex(13); - private final long connection = 12345L; + private final Cipher frameCipher; + private final ErasableKey frameKey; public ConnectionDecrypterImplTest() { super(); Injector i = Guice.createInjector(new CryptoModule()); CryptoComponent crypto = i.getInstance(CryptoComponent.class); - tagCipher = crypto.getTagCipher(); frameCipher = crypto.getFrameCipher(); - tagKey = crypto.generateTestKey(); frameKey = crypto.generateTestKey(); } @@ -51,12 +45,8 @@ 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); - 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[] iv = new byte[frameCipher.getBlockSize()]; byte[] ciphertext = new byte[123]; byte[] ciphertextMac = new byte[MAC_LENGTH]; IvParameterSpec ivSpec = new IvParameterSpec(iv); @@ -84,9 +74,8 @@ public class ConnectionDecrypterImplTest extends TestCase { out.write(ciphertextMac); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); // Use a ConnectionDecrypter to decrypt the ciphertext - ConnectionDecrypter d = new ConnectionDecrypterImpl(in, - IvEncoder.encodeIv(transportIndex.getInt(), connection), - frameCipher, frameKey); + ConnectionDecrypter d = new ConnectionDecrypterImpl(in, frameCipher, + frameKey); // First frame byte[] decrypted = new byte[ciphertext.length]; TestUtils.readFully(d.getInputStream(), decrypted); diff --git a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java index 1af4902cfd..b7463f0126 100644 --- a/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java +++ b/test/net/sf/briar/transport/ConnectionEncrypterImplTest.java @@ -1,17 +1,15 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import static org.junit.Assert.assertArrayEquals; import java.io.ByteArrayOutputStream; import javax.crypto.Cipher; -import net.sf.briar.api.crypto.ErasableKey; import javax.crypto.spec.IvParameterSpec; import junit.framework.TestCase; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.protocol.TransportIndex; +import net.sf.briar.api.crypto.ErasableKey; import net.sf.briar.crypto.CryptoModule; import org.junit.Test; @@ -25,8 +23,6 @@ public class ConnectionEncrypterImplTest extends TestCase { private final Cipher tagCipher, frameCipher; private final ErasableKey tagKey, frameKey; - private final TransportIndex transportIndex = new TransportIndex(13); - private final long connection = 12345L; public ConnectionEncrypterImplTest() { super(); @@ -49,12 +45,10 @@ 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); - tagCipher.init(Cipher.ENCRYPT_MODE, tagKey); - byte[] tag = tagCipher.doFinal(iv); - assertEquals(TAG_LENGTH, tag.length); + // Calculate the expected tag + byte[] tag = TagEncoder.encodeTag(0, tagCipher, tagKey); // Calculate the expected ciphertext for the first frame + byte[] iv = new byte[frameCipher.getBlockSize()]; byte[] plaintext = new byte[123]; byte[] plaintextMac = new byte[MAC_LENGTH]; IvParameterSpec ivSpec = new IvParameterSpec(iv); @@ -82,9 +76,8 @@ public class ConnectionEncrypterImplTest extends TestCase { byte[] expected = out.toByteArray(); // Use a ConnectionEncrypter to encrypt the plaintext out.reset(); - iv = IvEncoder.encodeIv(transportIndex.getInt(), connection); ConnectionEncrypter e = new ConnectionEncrypterImpl(out, Long.MAX_VALUE, - iv, tagCipher, frameCipher, tagKey, frameKey); + 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 2198b6402c..2ff78152bb 100644 --- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java +++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java @@ -617,8 +617,6 @@ public class ConnectionRecogniserImplTest extends TestCase { // 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 tagCipher.doFinal(iv); + return TagEncoder.encodeTag(0, tagCipher, tagKey); } } diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java index b15428f3ea..4c71859f51 100644 --- a/test/net/sf/briar/transport/FrameReadWriteTest.java +++ b/test/net/sf/briar/transport/FrameReadWriteTest.java @@ -11,11 +11,10 @@ import java.util.Random; import javax.crypto.Cipher; import javax.crypto.Mac; -import net.sf.briar.api.crypto.ErasableKey; import junit.framework.TestCase; import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.protocol.TransportIndex; +import net.sf.briar.api.crypto.ErasableKey; import net.sf.briar.api.transport.ConnectionReader; import net.sf.briar.api.transport.ConnectionWriter; import net.sf.briar.crypto.CryptoModule; @@ -33,8 +32,6 @@ public class FrameReadWriteTest extends TestCase { private final byte[] outSecret; private final ErasableKey tagKey, frameKey, macKey; private final Mac mac; - private final TransportIndex transportIndex = new TransportIndex(13); - private final long connection = 12345L; public FrameReadWriteTest() { super(); @@ -63,11 +60,8 @@ public class FrameReadWriteTest extends TestCase { } private void testWriteAndRead(boolean initiator) throws Exception { - // Create and encrypt the IV - byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection); - tagCipher.init(Cipher.ENCRYPT_MODE, tagKey); - byte[] tag = tagCipher.doFinal(iv); - assertEquals(TAG_LENGTH, tag.length); + // Encode the tag + byte[] tag = TagEncoder.encodeTag(0, tagCipher, tagKey); // Generate two random frames byte[] frame = new byte[12345]; random.nextBytes(frame); @@ -80,7 +74,7 @@ public class FrameReadWriteTest extends TestCase { // Write the frames ByteArrayOutputStream out = new ByteArrayOutputStream(); ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out, - Long.MAX_VALUE, iv, tagCipher, frameCipher, tagCopy, frameCopy); + Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy); ConnectionWriter writer = new ConnectionWriterImpl(encrypter, mac, macCopy); OutputStream out1 = writer.getOutputStream(); @@ -88,18 +82,14 @@ public class FrameReadWriteTest extends TestCase { out1.flush(); out1.write(frame1); out1.flush(); - // Read the IV back + // Read the tag back ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); byte[] recoveredTag = new byte[TAG_LENGTH]; assertEquals(TAG_LENGTH, in.read(recoveredTag)); assertArrayEquals(tag, recoveredTag); - // Decrypt the IV - tagCipher.init(Cipher.DECRYPT_MODE, tagKey); - byte[] recoveredIv = tagCipher.doFinal(recoveredTag); - iv = IvEncoder.encodeIv(transportIndex.getInt(), connection); - assertArrayEquals(iv, recoveredIv); + assertTrue(TagEncoder.validateTag(tag, 0, tagCipher, tagKey)); // Read the frames back - ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv, + ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, frameCipher, frameKey); ConnectionReader reader = new ConnectionReaderImpl(decrypter, mac, macKey); -- GitLab