mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 03:39:05 +01:00
The word "tag" was overloaded, so from now on use "tag" for the
predefined tags in the protocol and serial components, and "IV" for the encrypted IVs used to identify connections in the transport component.
This commit is contained in:
@@ -185,10 +185,10 @@ public class FileReadWriteTest extends TestCase {
|
||||
testWriteFile();
|
||||
|
||||
InputStream in = new FileInputStream(file);
|
||||
byte[] firstTag = new byte[16];
|
||||
byte[] iv = new byte[16];
|
||||
int offset = 0;
|
||||
while(offset < 16) {
|
||||
int read = in.read(firstTag, offset, firstTag.length - offset);
|
||||
int read = in.read(iv, offset, iv.length - offset);
|
||||
if(read == -1) break;
|
||||
offset += read;
|
||||
}
|
||||
|
||||
@@ -29,21 +29,21 @@ public class CryptoComponentTest extends TestCase {
|
||||
crypto.deriveOutgoingMacKey(bobSecret));
|
||||
assertEquals(crypto.deriveIncomingFrameKey(aliceSecret),
|
||||
crypto.deriveOutgoingFrameKey(bobSecret));
|
||||
assertEquals(crypto.deriveIncomingTagKey(aliceSecret),
|
||||
crypto.deriveOutgoingTagKey(bobSecret));
|
||||
assertEquals(crypto.deriveIncomingIvKey(aliceSecret),
|
||||
crypto.deriveOutgoingIvKey(bobSecret));
|
||||
// Check that Alice's outgoing keys match Bob's incoming keys
|
||||
assertEquals(crypto.deriveOutgoingMacKey(aliceSecret),
|
||||
crypto.deriveIncomingMacKey(bobSecret));
|
||||
assertEquals(crypto.deriveOutgoingFrameKey(aliceSecret),
|
||||
crypto.deriveIncomingFrameKey(bobSecret));
|
||||
assertEquals(crypto.deriveOutgoingTagKey(aliceSecret),
|
||||
crypto.deriveIncomingTagKey(bobSecret));
|
||||
assertEquals(crypto.deriveOutgoingIvKey(aliceSecret),
|
||||
crypto.deriveIncomingIvKey(bobSecret));
|
||||
// Check that Alice's incoming and outgoing keys are different
|
||||
assertFalse(crypto.deriveIncomingMacKey(aliceSecret).equals(
|
||||
crypto.deriveOutgoingMacKey(aliceSecret)));
|
||||
assertFalse(crypto.deriveIncomingFrameKey(aliceSecret).equals(
|
||||
crypto.deriveOutgoingFrameKey(aliceSecret)));
|
||||
assertFalse(crypto.deriveIncomingTagKey(aliceSecret).equals(
|
||||
crypto.deriveOutgoingTagKey(aliceSecret)));
|
||||
assertFalse(crypto.deriveIncomingIvKey(aliceSecret).equals(
|
||||
crypto.deriveOutgoingIvKey(aliceSecret)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Arrays;
|
||||
@@ -54,16 +54,16 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
||||
public void testDecryption() throws Exception {
|
||||
// Calculate the expected plaintext for the first frame
|
||||
byte[] ciphertext = new byte[123];
|
||||
byte[] ivBytes = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(ivBytes, transportId, connection, 0L);
|
||||
IvParameterSpec iv = new IvParameterSpec(ivBytes);
|
||||
frameCipher.init(Cipher.DECRYPT_MODE, frameKey, iv);
|
||||
byte[] iv = new byte[IV_LENGTH];
|
||||
IvEncoder.encodeIv(iv, transportId, connection, 0L);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] plaintext = frameCipher.doFinal(ciphertext);
|
||||
// Calculate the expected plaintext for the second frame
|
||||
byte[] ciphertext1 = new byte[1234];
|
||||
TagEncoder.encodeTag(ivBytes, transportId, connection, 1L);
|
||||
iv = new IvParameterSpec(ivBytes);
|
||||
frameCipher.init(Cipher.DECRYPT_MODE, frameKey, iv);
|
||||
IvEncoder.encodeIv(iv, transportId, connection, 1L);
|
||||
ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] plaintext1 = frameCipher.doFinal(ciphertext1);
|
||||
assertEquals(ciphertext1.length, plaintext1.length);
|
||||
// Concatenate the ciphertexts
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
@@ -22,8 +22,8 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
|
||||
private static final int MAC_LENGTH = 32;
|
||||
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final SecretKey tagKey, frameKey;
|
||||
private final Cipher ivCipher, frameCipher;
|
||||
private final SecretKey ivKey, frameKey;
|
||||
private final int transportId = 1234;
|
||||
private final long connection = 12345L;
|
||||
|
||||
@@ -31,9 +31,9 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
ivCipher = crypto.getIvCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
tagKey = crypto.generateSecretKey();
|
||||
ivKey = crypto.generateSecretKey();
|
||||
frameKey = crypto.generateSecretKey();
|
||||
}
|
||||
|
||||
@@ -41,27 +41,26 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
public void testSingleByteFrame() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ConnectionEncrypter e = new ConnectionEncrypterImpl(out, transportId,
|
||||
connection, tagCipher, frameCipher, tagKey, frameKey);
|
||||
connection, ivCipher, frameCipher, ivKey, frameKey);
|
||||
e.getOutputStream().write((byte) 0);
|
||||
e.writeMac(new byte[MAC_LENGTH]);
|
||||
assertEquals(TAG_LENGTH + 1 + MAC_LENGTH, out.toByteArray().length);
|
||||
assertEquals(IV_LENGTH + 1 + MAC_LENGTH, out.toByteArray().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryption() throws Exception {
|
||||
// Calculate the expected ciphertext for the tag
|
||||
byte[] plaintextTag = TagEncoder.encodeTag(transportId, connection);
|
||||
assertEquals(TAG_LENGTH, plaintextTag.length);
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = tagCipher.doFinal(plaintextTag);
|
||||
assertEquals(TAG_LENGTH, tag.length);
|
||||
// Calculate the expected ciphertext for the IV
|
||||
byte[] iv = IvEncoder.encodeIv(transportId, connection);
|
||||
assertEquals(IV_LENGTH, iv.length);
|
||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||
byte[] encryptedIv = ivCipher.doFinal(iv);
|
||||
assertEquals(IV_LENGTH, encryptedIv.length);
|
||||
// Calculate the expected ciphertext for the first frame
|
||||
byte[] plaintext = new byte[123];
|
||||
byte[] plaintextMac = new byte[MAC_LENGTH];
|
||||
byte[] ivBytes = new byte[TAG_LENGTH];
|
||||
TagEncoder.encodeTag(ivBytes, transportId, connection, 0L);
|
||||
IvParameterSpec iv = new IvParameterSpec(ivBytes);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, iv);
|
||||
IvEncoder.encodeIv(iv, transportId, connection, 0L);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext = new byte[plaintext.length + plaintextMac.length];
|
||||
int offset = frameCipher.update(plaintext, 0, plaintext.length,
|
||||
ciphertext);
|
||||
@@ -69,9 +68,9 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
offset);
|
||||
// Calculate the expected ciphertext for the second frame
|
||||
byte[] plaintext1 = new byte[1234];
|
||||
TagEncoder.encodeTag(ivBytes, transportId, connection, 1L);
|
||||
iv = new IvParameterSpec(ivBytes);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, iv);
|
||||
IvEncoder.encodeIv(iv, transportId, connection, 1L);
|
||||
ivSpec = new IvParameterSpec(iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
byte[] ciphertext1 = new byte[plaintext1.length + plaintextMac.length];
|
||||
offset = frameCipher.update(plaintext1, 0, plaintext1.length,
|
||||
ciphertext1);
|
||||
@@ -79,14 +78,14 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
||||
offset);
|
||||
// Concatenate the ciphertexts
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(tag);
|
||||
out.write(encryptedIv);
|
||||
out.write(ciphertext);
|
||||
out.write(ciphertext1);
|
||||
byte[] expected = out.toByteArray();
|
||||
// Use a ConnectionEncrypter to encrypt the plaintext
|
||||
out.reset();
|
||||
ConnectionEncrypter e = new ConnectionEncrypterImpl(out, transportId,
|
||||
connection, tagCipher, frameCipher, tagKey, frameKey);
|
||||
connection, ivCipher, frameCipher, ivKey, frameKey);
|
||||
e.getOutputStream().write(plaintext);
|
||||
e.writeMac(plaintextMac);
|
||||
e.getOutputStream().write(plaintext1);
|
||||
|
||||
@@ -33,6 +33,8 @@ public class ConnectionReaderImplTest extends TestCase {
|
||||
mac.init(crypto.generateSecretKey());
|
||||
}
|
||||
|
||||
// FIXME: Test corner cases and corrupt frames
|
||||
|
||||
@Test
|
||||
public void testSingleByteFrame() throws Exception {
|
||||
// Six bytes for the header, one for the payload
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -41,7 +41,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnexpectedTag() throws Exception {
|
||||
public void testUnexpectedIv() throws Exception {
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
context.checking(new Expectations() {{
|
||||
@@ -55,18 +55,18 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
||||
}});
|
||||
final ConnectionRecogniserImpl c =
|
||||
new ConnectionRecogniserImpl(transportId, crypto, db);
|
||||
assertNull(c.acceptConnection(new byte[TAG_LENGTH]));
|
||||
assertNull(c.acceptConnection(new byte[IV_LENGTH]));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpectedTag() throws Exception {
|
||||
// Calculate the expected tag for connection number 3
|
||||
SecretKey tagKey = crypto.deriveIncomingTagKey(secret);
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = TagEncoder.encodeTag(transportId, 3L);
|
||||
byte[] encryptedTag = tagCipher.doFinal(tag);
|
||||
public void testExpectedIv() throws Exception {
|
||||
// Calculate the expected IV for connection number 3
|
||||
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
|
||||
Cipher ivCipher = crypto.getIvCipher();
|
||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||
byte[] iv = IvEncoder.encodeIv(transportId, 3L);
|
||||
byte[] encryptedIv = ivCipher.doFinal(iv);
|
||||
|
||||
Mockery context = new Mockery();
|
||||
final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
@@ -83,10 +83,10 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
||||
}});
|
||||
final ConnectionRecogniserImpl c =
|
||||
new ConnectionRecogniserImpl(transportId, crypto, db);
|
||||
// First time - the tag should be expected
|
||||
assertEquals(contactId, c.acceptConnection(encryptedTag));
|
||||
// Second time - the tag should no longer be expected
|
||||
assertNull(c.acceptConnection(encryptedTag));
|
||||
// First time - the IV should be expected
|
||||
assertEquals(contactId, c.acceptConnection(encryptedIv));
|
||||
// Second time - the IV should no longer be expected
|
||||
assertNull(c.acceptConnection(encryptedIv));
|
||||
// The window should have advanced
|
||||
assertEquals(4L, connectionWindow.getCentre());
|
||||
Collection<Long> unseen = connectionWindow.getUnseenConnectionNumbers();
|
||||
|
||||
@@ -30,6 +30,8 @@ public class ConnectionWriterImplTest extends TestCase {
|
||||
mac.init(crypto.generateSecretKey());
|
||||
}
|
||||
|
||||
// FIXME: Test corner cases
|
||||
|
||||
@Test
|
||||
public void testSingleByteFrame() throws Exception {
|
||||
// Six bytes for the header, one for the payload
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -27,8 +27,8 @@ import com.google.inject.Injector;
|
||||
public class FrameReadWriteTest extends TestCase {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final SecretKey macKey, tagKey, frameKey;
|
||||
private final Cipher ivCipher, frameCipher;
|
||||
private final SecretKey ivKey, frameKey, macKey;
|
||||
private final Mac mac;
|
||||
private final Random random;
|
||||
private final byte[] secret = new byte[100];
|
||||
@@ -39,24 +39,24 @@ public class FrameReadWriteTest extends TestCase {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
tagCipher = crypto.getTagCipher();
|
||||
ivCipher = crypto.getIvCipher();
|
||||
frameCipher = crypto.getFrameCipher();
|
||||
// Since we're sending packets to ourselves, we only need outgoing keys
|
||||
macKey = crypto.deriveOutgoingMacKey(secret);
|
||||
tagKey = crypto.deriveOutgoingTagKey(secret);
|
||||
// Since we're sending frames to ourselves, we only need outgoing keys
|
||||
ivKey = crypto.deriveOutgoingIvKey(secret);
|
||||
frameKey = crypto.deriveOutgoingFrameKey(secret);
|
||||
macKey = crypto.deriveOutgoingMacKey(secret);
|
||||
mac = crypto.getMac();
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteAndRead() throws Exception {
|
||||
// Calculate the expected ciphertext for the tag
|
||||
byte[] plaintextTag = TagEncoder.encodeTag(transportId, connection);
|
||||
assertEquals(TAG_LENGTH, plaintextTag.length);
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
byte[] tag = tagCipher.doFinal(plaintextTag);
|
||||
assertEquals(TAG_LENGTH, tag.length);
|
||||
// Calculate the expected ciphertext for the IV
|
||||
byte[] iv = IvEncoder.encodeIv(transportId, connection);
|
||||
assertEquals(IV_LENGTH, iv.length);
|
||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||
byte[] encryptedIv = ivCipher.doFinal(iv);
|
||||
assertEquals(IV_LENGTH, encryptedIv.length);
|
||||
// Generate two random frames
|
||||
byte[] frame = new byte[12345];
|
||||
random.nextBytes(frame);
|
||||
@@ -65,7 +65,7 @@ public class FrameReadWriteTest extends TestCase {
|
||||
// Write the frames
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||
transportId, connection, tagCipher, frameCipher, tagKey,
|
||||
transportId, connection, ivCipher, frameCipher, ivKey,
|
||||
frameKey);
|
||||
mac.init(macKey);
|
||||
ConnectionWriter writer = new ConnectionWriterImpl(encrypter, mac);
|
||||
@@ -76,9 +76,9 @@ public class FrameReadWriteTest extends TestCase {
|
||||
out1.flush();
|
||||
// Read the frames back
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
byte[] recoveredTag = new byte[TAG_LENGTH];
|
||||
assertEquals(TAG_LENGTH, in.read(recoveredTag));
|
||||
assertTrue(Arrays.equals(tag, recoveredTag));
|
||||
byte[] recoveredIv = new byte[IV_LENGTH];
|
||||
assertEquals(IV_LENGTH, in.read(recoveredIv));
|
||||
assertTrue(Arrays.equals(encryptedIv, recoveredIv));
|
||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in,
|
||||
transportId, connection, frameCipher, frameKey);
|
||||
ConnectionReader reader = new ConnectionReaderImpl(decrypter, mac);
|
||||
|
||||
Reference in New Issue
Block a user