mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Moved batch ID calculation off the IO thread.
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
<test name='net.sf.briar.protocol.ProtocolReadWriteTest'/>
|
||||
<test name='net.sf.briar.protocol.ProtocolWriterImplTest'/>
|
||||
<test name='net.sf.briar.protocol.RequestReaderTest'/>
|
||||
<test name='net.sf.briar.protocol.UnverifiedBatchImplTest'/>
|
||||
<test name='net.sf.briar.serial.ReaderImplTest'/>
|
||||
<test name='net.sf.briar.serial.WriterImplTest'/>
|
||||
<test name='net.sf.briar.setup.SetupWorkerTest'/>
|
||||
|
||||
@@ -7,9 +7,6 @@ import java.util.Collections;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.ProtocolConstants;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.protocol.UnverifiedBatch;
|
||||
@@ -18,7 +15,6 @@ import net.sf.briar.api.serial.Reader;
|
||||
import net.sf.briar.api.serial.ReaderFactory;
|
||||
import net.sf.briar.api.serial.Writer;
|
||||
import net.sf.briar.api.serial.WriterFactory;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
import net.sf.briar.serial.SerialModule;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
@@ -32,18 +28,15 @@ public class BatchReaderTest extends TestCase {
|
||||
|
||||
private final ReaderFactory readerFactory;
|
||||
private final WriterFactory writerFactory;
|
||||
private final CryptoComponent crypto;
|
||||
private final Mockery context;
|
||||
private final UnverifiedMessage message;
|
||||
private final ObjectReader<UnverifiedMessage> messageReader;
|
||||
|
||||
public BatchReaderTest() throws Exception {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new SerialModule(),
|
||||
new CryptoModule());
|
||||
Injector i = Guice.createInjector(new SerialModule());
|
||||
readerFactory = i.getInstance(ReaderFactory.class);
|
||||
writerFactory = i.getInstance(WriterFactory.class);
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
context = new Mockery();
|
||||
message = context.mock(UnverifiedMessage.class);
|
||||
messageReader = new TestMessageReader();
|
||||
@@ -53,8 +46,7 @@ public class BatchReaderTest extends TestCase {
|
||||
public void testFormatExceptionIfBatchIsTooLarge() throws Exception {
|
||||
UnverifiedBatchFactory batchFactory =
|
||||
context.mock(UnverifiedBatchFactory.class);
|
||||
BatchReader batchReader = new BatchReader(crypto, messageReader,
|
||||
batchFactory);
|
||||
BatchReader batchReader = new BatchReader(messageReader, batchFactory);
|
||||
|
||||
byte[] b = createBatch(ProtocolConstants.MAX_PACKET_LENGTH + 1);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
@@ -72,12 +64,11 @@ public class BatchReaderTest extends TestCase {
|
||||
public void testNoFormatExceptionIfBatchIsMaximumSize() throws Exception {
|
||||
final UnverifiedBatchFactory batchFactory =
|
||||
context.mock(UnverifiedBatchFactory.class);
|
||||
BatchReader batchReader = new BatchReader(crypto, messageReader,
|
||||
batchFactory);
|
||||
BatchReader batchReader = new BatchReader(messageReader, batchFactory);
|
||||
final UnverifiedBatch batch = context.mock(UnverifiedBatch.class);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(batchFactory).createUnverifiedBatch(with(any(BatchId.class)),
|
||||
with(Collections.singletonList(message)));
|
||||
oneOf(batchFactory).createUnverifiedBatch(
|
||||
Collections.singletonList(message));
|
||||
will(returnValue(batch));
|
||||
}});
|
||||
|
||||
@@ -91,41 +82,11 @@ public class BatchReaderTest extends TestCase {
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchId() throws Exception {
|
||||
byte[] b = createBatch(ProtocolConstants.MAX_PACKET_LENGTH);
|
||||
// Calculate the expected batch ID
|
||||
MessageDigest messageDigest = crypto.getMessageDigest();
|
||||
messageDigest.update(b);
|
||||
final BatchId id = new BatchId(messageDigest.digest());
|
||||
|
||||
final UnverifiedBatchFactory batchFactory =
|
||||
context.mock(UnverifiedBatchFactory.class);
|
||||
BatchReader batchReader = new BatchReader(crypto, messageReader,
|
||||
batchFactory);
|
||||
final UnverifiedBatch batch = context.mock(UnverifiedBatch.class);
|
||||
context.checking(new Expectations() {{
|
||||
// Check that the batch ID matches the expected ID
|
||||
oneOf(batchFactory).createUnverifiedBatch(with(id),
|
||||
with(Collections.singletonList(message)));
|
||||
will(returnValue(batch));
|
||||
}});
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
Reader reader = readerFactory.createReader(in);
|
||||
reader.addObjectReader(Types.BATCH, batchReader);
|
||||
|
||||
assertEquals(batch, reader.readStruct(Types.BATCH,
|
||||
UnverifiedBatch.class));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyBatch() throws Exception {
|
||||
final UnverifiedBatchFactory batchFactory =
|
||||
context.mock(UnverifiedBatchFactory.class);
|
||||
BatchReader batchReader = new BatchReader(crypto, messageReader,
|
||||
batchFactory);
|
||||
BatchReader batchReader = new BatchReader(messageReader, batchFactory);
|
||||
|
||||
byte[] b = createEmptyBatch();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(b);
|
||||
|
||||
242
test/net/sf/briar/protocol/UnverifiedBatchImplTest.java
Normal file
242
test/net/sf/briar/protocol/UnverifiedBatchImplTest.java
Normal file
@@ -0,0 +1,242 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.Signature;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.briar.TestUtils;
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.MessageDigest;
|
||||
import net.sf.briar.api.protocol.Author;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.UnverifiedBatch;
|
||||
import net.sf.briar.crypto.CryptoModule;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
public class UnverifiedBatchImplTest extends TestCase {
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
private final byte[] raw, raw1;
|
||||
private final String subject;
|
||||
private final long timestamp;
|
||||
|
||||
public UnverifiedBatchImplTest() {
|
||||
super();
|
||||
Injector i = Guice.createInjector(new CryptoModule());
|
||||
crypto = i.getInstance(CryptoComponent.class);
|
||||
Random r = new Random();
|
||||
raw = new byte[123];
|
||||
r.nextBytes(raw);
|
||||
raw1 = new byte[1234];
|
||||
r.nextBytes(raw1);
|
||||
subject = "Unit tests are exciting";
|
||||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIds() throws Exception {
|
||||
// Calculate the expected batch and message IDs
|
||||
MessageDigest messageDigest = crypto.getMessageDigest();
|
||||
messageDigest.update(raw);
|
||||
messageDigest.update(raw1);
|
||||
BatchId batchId = new BatchId(messageDigest.digest());
|
||||
messageDigest.update(raw);
|
||||
MessageId messageId = new MessageId(messageDigest.digest());
|
||||
messageDigest.update(raw1);
|
||||
MessageId messageId1 = new MessageId(messageDigest.digest());
|
||||
// Verify the batch
|
||||
Mockery context = new Mockery();
|
||||
final UnverifiedMessage message =
|
||||
context.mock(UnverifiedMessage.class, "message");
|
||||
final UnverifiedMessage message1 =
|
||||
context.mock(UnverifiedMessage.class, "message1");
|
||||
context.checking(new Expectations() {{
|
||||
// First message
|
||||
oneOf(message).getRaw();
|
||||
will(returnValue(raw));
|
||||
oneOf(message).getAuthor();
|
||||
will(returnValue(null));
|
||||
oneOf(message).getGroup();
|
||||
will(returnValue(null));
|
||||
oneOf(message).getParent();
|
||||
will(returnValue(null));
|
||||
oneOf(message).getSubject();
|
||||
will(returnValue(subject));
|
||||
oneOf(message).getTimestamp();
|
||||
will(returnValue(timestamp));
|
||||
oneOf(message).getBodyStart();
|
||||
will(returnValue(10));
|
||||
oneOf(message).getBodyLength();
|
||||
will(returnValue(100));
|
||||
// Second message
|
||||
oneOf(message1).getRaw();
|
||||
will(returnValue(raw1));
|
||||
oneOf(message1).getAuthor();
|
||||
will(returnValue(null));
|
||||
oneOf(message1).getGroup();
|
||||
will(returnValue(null));
|
||||
oneOf(message1).getParent();
|
||||
will(returnValue(null));
|
||||
oneOf(message1).getSubject();
|
||||
will(returnValue(subject));
|
||||
oneOf(message1).getTimestamp();
|
||||
will(returnValue(timestamp));
|
||||
oneOf(message1).getBodyStart();
|
||||
will(returnValue(10));
|
||||
oneOf(message1).getBodyLength();
|
||||
will(returnValue(1000));
|
||||
}});
|
||||
Collection<UnverifiedMessage> messages =
|
||||
Arrays.asList(new UnverifiedMessage[] {message, message1});
|
||||
UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages);
|
||||
Batch verifiedBatch = batch.verify();
|
||||
// Check that the batch and message IDs match
|
||||
assertEquals(batchId, verifiedBatch.getId());
|
||||
Collection<Message> verifiedMessages = verifiedBatch.getMessages();
|
||||
assertEquals(2, verifiedMessages.size());
|
||||
Iterator<Message> it = verifiedMessages.iterator();
|
||||
Message verifiedMessage = it.next();
|
||||
assertEquals(messageId, verifiedMessage.getId());
|
||||
Message verifiedMessage1 = it.next();
|
||||
assertEquals(messageId1, verifiedMessage1.getId());
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignatures() throws Exception {
|
||||
final int signedByAuthor = 100, signedByGroup = 110;
|
||||
final KeyPair authorKeyPair = crypto.generateKeyPair();
|
||||
final KeyPair groupKeyPair = crypto.generateKeyPair();
|
||||
Signature signature = crypto.getSignature();
|
||||
// Calculate the expected author and group signatures
|
||||
signature.initSign(authorKeyPair.getPrivate());
|
||||
signature.update(raw, 0, signedByAuthor);
|
||||
final byte[] authorSignature = signature.sign();
|
||||
signature.initSign(groupKeyPair.getPrivate());
|
||||
signature.update(raw, 0, signedByGroup);
|
||||
final byte[] groupSignature = signature.sign();
|
||||
// Verify the batch
|
||||
Mockery context = new Mockery();
|
||||
final UnverifiedMessage message =
|
||||
context.mock(UnverifiedMessage.class, "message");
|
||||
final Author author = context.mock(Author.class);
|
||||
final Group group = context.mock(Group.class);
|
||||
final UnverifiedMessage message1 =
|
||||
context.mock(UnverifiedMessage.class, "message1");
|
||||
context.checking(new Expectations() {{
|
||||
// First message
|
||||
oneOf(message).getRaw();
|
||||
will(returnValue(raw));
|
||||
oneOf(message).getAuthor();
|
||||
will(returnValue(author));
|
||||
oneOf(author).getPublicKey();
|
||||
will(returnValue(authorKeyPair.getPublic().getEncoded()));
|
||||
oneOf(message).getLengthSignedByAuthor();
|
||||
will(returnValue(signedByAuthor));
|
||||
oneOf(message).getAuthorSignature();
|
||||
will(returnValue(authorSignature));
|
||||
oneOf(message).getGroup();
|
||||
will(returnValue(group));
|
||||
exactly(2).of(group).getPublicKey();
|
||||
will(returnValue(groupKeyPair.getPublic().getEncoded()));
|
||||
oneOf(message).getLengthSignedByGroup();
|
||||
will(returnValue(signedByGroup));
|
||||
oneOf(message).getGroupSignature();
|
||||
will(returnValue(groupSignature));
|
||||
oneOf(author).getId();
|
||||
will(returnValue(new AuthorId(TestUtils.getRandomId())));
|
||||
oneOf(group).getId();
|
||||
will(returnValue(new GroupId(TestUtils.getRandomId())));
|
||||
oneOf(message).getParent();
|
||||
will(returnValue(null));
|
||||
oneOf(message).getSubject();
|
||||
will(returnValue(subject));
|
||||
oneOf(message).getTimestamp();
|
||||
will(returnValue(timestamp));
|
||||
oneOf(message).getBodyStart();
|
||||
will(returnValue(10));
|
||||
oneOf(message).getBodyLength();
|
||||
will(returnValue(100));
|
||||
// Second message
|
||||
oneOf(message1).getRaw();
|
||||
will(returnValue(raw1));
|
||||
oneOf(message1).getAuthor();
|
||||
will(returnValue(null));
|
||||
oneOf(message1).getGroup();
|
||||
will(returnValue(null));
|
||||
oneOf(message1).getParent();
|
||||
will(returnValue(null));
|
||||
oneOf(message1).getSubject();
|
||||
will(returnValue(subject));
|
||||
oneOf(message1).getTimestamp();
|
||||
will(returnValue(timestamp));
|
||||
oneOf(message1).getBodyStart();
|
||||
will(returnValue(10));
|
||||
oneOf(message1).getBodyLength();
|
||||
will(returnValue(1000));
|
||||
}});
|
||||
Collection<UnverifiedMessage> messages =
|
||||
Arrays.asList(new UnverifiedMessage[] {message, message1});
|
||||
UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages);
|
||||
batch.verify();
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionThrownIfMessageIsModified() throws Exception {
|
||||
final int signedByAuthor = 100;
|
||||
final KeyPair authorKeyPair = crypto.generateKeyPair();
|
||||
Signature signature = crypto.getSignature();
|
||||
// Calculate the expected author signature
|
||||
signature.initSign(authorKeyPair.getPrivate());
|
||||
signature.update(raw, 0, signedByAuthor);
|
||||
final byte[] authorSignature = signature.sign();
|
||||
// Modify the message
|
||||
raw[signedByAuthor / 2] ^= 0xff;
|
||||
// Verify the batch
|
||||
Mockery context = new Mockery();
|
||||
final UnverifiedMessage message =
|
||||
context.mock(UnverifiedMessage.class, "message");
|
||||
final Author author = context.mock(Author.class);
|
||||
final UnverifiedMessage message1 =
|
||||
context.mock(UnverifiedMessage.class, "message1");
|
||||
context.checking(new Expectations() {{
|
||||
// First message - verification will fail at the author's signature
|
||||
oneOf(message).getRaw();
|
||||
will(returnValue(raw));
|
||||
oneOf(message).getAuthor();
|
||||
will(returnValue(author));
|
||||
oneOf(author).getPublicKey();
|
||||
will(returnValue(authorKeyPair.getPublic().getEncoded()));
|
||||
oneOf(message).getLengthSignedByAuthor();
|
||||
will(returnValue(signedByAuthor));
|
||||
oneOf(message).getAuthorSignature();
|
||||
will(returnValue(authorSignature));
|
||||
}});
|
||||
Collection<UnverifiedMessage> messages =
|
||||
Arrays.asList(new UnverifiedMessage[] {message, message1});
|
||||
UnverifiedBatch batch = new UnverifiedBatchImpl(crypto, messages);
|
||||
try {
|
||||
batch.verify();
|
||||
fail();
|
||||
} catch(GeneralSecurityException expected) {}
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user