mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Validate New Messages for Reblogging and Comments of Blog Posts
Also includes unit tests for the new message types. Closes #591
This commit is contained in:
@@ -18,9 +18,11 @@ import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorId;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupFactory;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.InvalidMessageException;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageFactory;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.system.SystemClock;
|
||||
@@ -34,10 +36,17 @@ import java.security.GeneralSecurityException;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_COMMENT;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_CONTENT_TYPE;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_CURRENT_MSG_ID;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_ORIGINAL_MSG_ID;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
|
||||
import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
|
||||
import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
|
||||
import static org.briarproject.api.blogs.MessageType.COMMENT;
|
||||
import static org.briarproject.api.blogs.MessageType.POST;
|
||||
import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT;
|
||||
import static org.briarproject.api.blogs.MessageType.WRAPPED_POST;
|
||||
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -47,11 +56,17 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
private final Mockery context = new Mockery();
|
||||
private final Blog blog;
|
||||
private final Author author;
|
||||
private final BdfDictionary authorDict;
|
||||
private final ClientId clientId;
|
||||
private final byte[] descriptor;
|
||||
private final Group group;
|
||||
private final Message message;
|
||||
private final BlogPostValidator validator;
|
||||
private final CryptoComponent cryptoComponent =
|
||||
context.mock(CryptoComponent.class);
|
||||
private final GroupFactory groupFactory = context.mock(GroupFactory.class);
|
||||
private final MessageFactory messageFactory =
|
||||
context.mock(MessageFactory.class);
|
||||
private final BlogFactory blogFactory = context.mock(BlogFactory.class);
|
||||
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||
private final Clock clock = new SystemClock();
|
||||
@@ -61,12 +76,18 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
|
||||
public BlogPostValidatorTest() {
|
||||
GroupId groupId = new GroupId(TestUtils.getRandomId());
|
||||
ClientId clientId = new ClientId(TestUtils.getRandomId());
|
||||
byte[] descriptor = TestUtils.getRandomBytes(12);
|
||||
clientId = BlogManagerImpl.CLIENT_ID;
|
||||
descriptor = TestUtils.getRandomBytes(42);
|
||||
group = new Group(groupId, clientId, descriptor);
|
||||
AuthorId authorId = new AuthorId(TestUtils.getRandomBytes(AuthorId.LENGTH));
|
||||
AuthorId authorId =
|
||||
new AuthorId(TestUtils.getRandomBytes(AuthorId.LENGTH));
|
||||
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||
author = new Author(authorId, "Author", publicKey);
|
||||
authorDict = BdfDictionary.of(
|
||||
new BdfEntry(KEY_AUTHOR_ID, author.getId()),
|
||||
new BdfEntry(KEY_AUTHOR_NAME, author.getName()),
|
||||
new BdfEntry(KEY_PUBLIC_KEY, author.getPublicKey())
|
||||
);
|
||||
blog = new Blog(group, "Test Blog", "", author);
|
||||
|
||||
MessageId messageId = new MessageId(TestUtils.getRandomId());
|
||||
@@ -75,29 +96,27 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
message = new Message(messageId, group.getId(), timestamp, raw);
|
||||
|
||||
MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class);
|
||||
validator = new BlogPostValidator(cryptoComponent, blogFactory,
|
||||
clientHelper, metadataEncoder, clock);
|
||||
validator = new BlogPostValidator(cryptoComponent, groupFactory,
|
||||
messageFactory, blogFactory, clientHelper, metadataEncoder,
|
||||
clock);
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateProperBlogPost()
|
||||
throws IOException, GeneralSecurityException {
|
||||
// Parent ID, content type, title (optional), post body, attachments
|
||||
// content type, title (optional), post body, attachments
|
||||
BdfList content = BdfList.of(null, contentType, null, body, null);
|
||||
final byte[] sigBytes = TestUtils.getRandomBytes(42);
|
||||
BdfList m = BdfList.of(content, sigBytes);
|
||||
BdfList m = BdfList.of(POST.getInt(), content, sigBytes);
|
||||
|
||||
expectCrypto(m, true);
|
||||
BdfList signed =
|
||||
BdfList.of(blog.getId(), message.getTimestamp(), content);
|
||||
expectCrypto(signed, sigBytes, true);
|
||||
final BdfDictionary result =
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
|
||||
assertEquals(contentType, result.getString(KEY_CONTENT_TYPE));
|
||||
BdfDictionary authorDict = BdfDictionary.of(
|
||||
new BdfEntry(KEY_AUTHOR_ID, author.getId()),
|
||||
new BdfEntry(KEY_AUTHOR_NAME, author.getName()),
|
||||
new BdfEntry(KEY_PUBLIC_KEY, author.getPublicKey())
|
||||
);
|
||||
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR));
|
||||
assertFalse(result.getBoolean(KEY_READ));
|
||||
context.assertIsSatisfied();
|
||||
@@ -107,7 +126,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
public void testValidateBlogPostWithoutAttachments()
|
||||
throws IOException, GeneralSecurityException {
|
||||
BdfList content = BdfList.of(null, contentType, null, body);
|
||||
BdfList m = BdfList.of(content, null);
|
||||
BdfList m = BdfList.of(POST.getInt(), content, null);
|
||||
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
}
|
||||
@@ -116,7 +135,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
public void testValidateBlogPostWithoutSignature()
|
||||
throws IOException, GeneralSecurityException {
|
||||
BdfList content = BdfList.of(null, contentType, null, body, null);
|
||||
BdfList m = BdfList.of(content, null);
|
||||
BdfList m = BdfList.of(POST.getInt(), content, null);
|
||||
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
}
|
||||
@@ -124,27 +143,149 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
@Test(expected = InvalidMessageException.class)
|
||||
public void testValidateBlogPostWithBadSignature()
|
||||
throws IOException, GeneralSecurityException {
|
||||
// Parent ID, content type, title (optional), post body, attachments
|
||||
// content type, title (optional), post body, attachments
|
||||
BdfList content = BdfList.of(null, contentType, null, body, null);
|
||||
final byte[] sigBytes = TestUtils.getRandomBytes(42);
|
||||
BdfList m = BdfList.of(content, sigBytes);
|
||||
BdfList m = BdfList.of(POST.getInt(), content, sigBytes);
|
||||
|
||||
expectCrypto(m, false);
|
||||
BdfList signed =
|
||||
BdfList.of(blog.getId(), message.getTimestamp(), content);
|
||||
expectCrypto(signed, sigBytes, false);
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
}
|
||||
|
||||
private void expectCrypto(BdfList m, final boolean pass)
|
||||
@Test
|
||||
public void testValidateProperBlogComment()
|
||||
throws IOException, GeneralSecurityException {
|
||||
// comment, parent_original_id, signature, parent_current_id
|
||||
String comment = "This is a blog comment";
|
||||
MessageId originalId = new MessageId(TestUtils.getRandomId());
|
||||
byte[] currentId = TestUtils.getRandomId();
|
||||
final byte[] sigBytes = TestUtils.getRandomBytes(42);
|
||||
BdfList m = BdfList.of(COMMENT.getInt(), comment, originalId,
|
||||
sigBytes, currentId);
|
||||
|
||||
BdfList signed =
|
||||
BdfList.of(blog.getId(), message.getTimestamp(), comment,
|
||||
originalId);
|
||||
expectCrypto(signed, sigBytes, true);
|
||||
final BdfDictionary result =
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
|
||||
assertEquals(comment, result.getString(KEY_COMMENT));
|
||||
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR));
|
||||
assertEquals(originalId.getBytes(), result.getRaw(KEY_ORIGINAL_MSG_ID));
|
||||
assertEquals(currentId, result.getRaw(KEY_CURRENT_MSG_ID));
|
||||
assertFalse(result.getBoolean(KEY_READ));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateProperEmptyBlogComment()
|
||||
throws IOException, GeneralSecurityException {
|
||||
// comment, parent_original_id, signature, parent_current_id
|
||||
MessageId originalId = new MessageId(TestUtils.getRandomId());
|
||||
byte[] currentId = TestUtils.getRandomId();
|
||||
final byte[] sigBytes = TestUtils.getRandomBytes(42);
|
||||
BdfList m = BdfList.of(COMMENT.getInt(), null, originalId, sigBytes,
|
||||
currentId);
|
||||
|
||||
BdfList signed =
|
||||
BdfList.of(blog.getId(), message.getTimestamp(), null,
|
||||
originalId);
|
||||
expectCrypto(signed, sigBytes, true);
|
||||
final BdfDictionary result =
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
|
||||
assertFalse(result.containsKey(KEY_COMMENT));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateProperWrappedPost()
|
||||
throws IOException, GeneralSecurityException {
|
||||
// group descriptor, timestamp, content, signature
|
||||
BdfList content = BdfList.of(null, contentType, null, body, null);
|
||||
final byte[] sigBytes = TestUtils.getRandomBytes(42);
|
||||
BdfList m =
|
||||
BdfList.of(WRAPPED_POST.getInt(), descriptor,
|
||||
message.getTimestamp(), content, sigBytes);
|
||||
|
||||
BdfList signed =
|
||||
BdfList.of(blog.getId(), message.getTimestamp(), content);
|
||||
expectCrypto(signed, sigBytes, true);
|
||||
|
||||
final BdfList originalList = BdfList.of(content, sigBytes);
|
||||
final byte[] originalBody = TestUtils.getRandomBytes(42);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(groupFactory).createGroup(clientId, descriptor);
|
||||
will(returnValue(blog.getGroup()));
|
||||
oneOf(clientHelper).toByteArray(originalList);
|
||||
will(returnValue(originalBody));
|
||||
oneOf(messageFactory)
|
||||
.createMessage(group.getId(), message.getTimestamp(),
|
||||
originalBody);
|
||||
will(returnValue(message));
|
||||
}});
|
||||
|
||||
final BdfDictionary result =
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
|
||||
assertEquals(contentType, result.getString(KEY_CONTENT_TYPE));
|
||||
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateProperWrappedComment()
|
||||
throws IOException, GeneralSecurityException {
|
||||
// group descriptor, timestamp, comment, parent_original_id, signature,
|
||||
// parent_current_id
|
||||
String comment = "This is another comment";
|
||||
MessageId originalId = new MessageId(TestUtils.getRandomId());
|
||||
final byte[] sigBytes = TestUtils.getRandomBytes(42);
|
||||
MessageId currentId = new MessageId(TestUtils.getRandomId());
|
||||
BdfList m = BdfList.of(WRAPPED_COMMENT.getInt(), descriptor,
|
||||
message.getTimestamp(), comment, originalId, sigBytes,
|
||||
currentId);
|
||||
|
||||
BdfList signed = BdfList.of(blog.getId(), message.getTimestamp(),
|
||||
comment, originalId);
|
||||
expectCrypto(signed, sigBytes, true);
|
||||
|
||||
final BdfList originalList = BdfList.of(comment, originalId, sigBytes,
|
||||
currentId);
|
||||
final byte[] originalBody = TestUtils.getRandomBytes(42);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(groupFactory).createGroup(clientId, descriptor);
|
||||
will(returnValue(blog.getGroup()));
|
||||
oneOf(clientHelper).toByteArray(originalList);
|
||||
will(returnValue(originalBody));
|
||||
oneOf(messageFactory)
|
||||
.createMessage(group.getId(), message.getTimestamp(),
|
||||
originalBody);
|
||||
will(returnValue(message));
|
||||
}});
|
||||
|
||||
final BdfDictionary result =
|
||||
validator.validateMessage(message, group, m).getDictionary();
|
||||
|
||||
assertEquals(comment, result.getString(KEY_COMMENT));
|
||||
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR));
|
||||
assertEquals(
|
||||
message.getId().getBytes(), result.getRaw(KEY_ORIGINAL_MSG_ID));
|
||||
assertEquals(currentId.getBytes(), result.getRaw(KEY_CURRENT_MSG_ID));
|
||||
context.assertIsSatisfied();
|
||||
}
|
||||
|
||||
private void expectCrypto(final BdfList signed, final byte[] sig,
|
||||
final boolean pass) throws IOException, GeneralSecurityException {
|
||||
final Signature signature = context.mock(Signature.class);
|
||||
final KeyParser keyParser = context.mock(KeyParser.class);
|
||||
final PublicKey publicKey = context.mock(PublicKey.class);
|
||||
|
||||
final BdfList content = m.getList(0);
|
||||
final byte[] sigBytes = m.getRaw(1);
|
||||
|
||||
final BdfList signed =
|
||||
BdfList.of(blog.getId(), message.getTimestamp(), content);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(blogFactory).parseBlog(group, "");
|
||||
will(returnValue(blog));
|
||||
@@ -156,9 +297,9 @@ public class BlogPostValidatorTest extends BriarTestCase {
|
||||
will(returnValue(signature));
|
||||
oneOf(signature).initVerify(publicKey);
|
||||
oneOf(clientHelper).toByteArray(signed);
|
||||
will(returnValue(sigBytes));
|
||||
oneOf(signature).update(sigBytes);
|
||||
oneOf(signature).verify(sigBytes);
|
||||
will(returnValue(sig));
|
||||
oneOf(signature).update(sig);
|
||||
oneOf(signature).verify(sig);
|
||||
will(returnValue(pass));
|
||||
}});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user