diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java index e85b15d7df3426298fd5139bf05d12041a4da2b7..a31e7737000a80d1511c5e9e57fa3bb1c5880bcd 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java @@ -7,5 +7,7 @@ public interface MessageFactory { Message createMessage(GroupId g, long timestamp, byte[] body); + Message createMessage(byte[] raw); + Message createMessage(MessageId m, byte[] raw); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java index 5a46a4aad5287d4e896778834681b703ae0336aa..0e34cf6b4db4005ce63088346d7e0b036be42346 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java @@ -20,6 +20,9 @@ import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; @NotNullByDefault class GroupFactoryImpl implements GroupFactory { + private static final byte[] FORMAT_VERSION_BYTES = + new byte[] {FORMAT_VERSION}; + private final CryptoComponent crypto; @Inject @@ -31,7 +34,7 @@ class GroupFactoryImpl implements GroupFactory { public Group createGroup(ClientId c, int majorVersion, byte[] descriptor) { byte[] majorVersionBytes = new byte[INT_32_BYTES]; ByteUtils.writeUint32(majorVersion, majorVersionBytes, 0); - byte[] hash = crypto.hash(LABEL, new byte[] {FORMAT_VERSION}, + byte[] hash = crypto.hash(LABEL, FORMAT_VERSION_BYTES, StringUtils.toUtf8(c.getString()), majorVersionBytes, descriptor); return new Group(new GroupId(hash), c, majorVersion, descriptor); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java index 8e8151079fcbd3f3a71c4ca3efd5090708ab1d67..754f0edac58ed70f648ac2983ae70e21e35bf051 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java @@ -24,6 +24,9 @@ import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES; @NotNullByDefault class MessageFactoryImpl implements MessageFactory { + private static final byte[] FORMAT_VERSION_BYTES = + new byte[] {FORMAT_VERSION}; + private final CryptoComponent crypto; @Inject @@ -35,14 +38,7 @@ class MessageFactoryImpl implements MessageFactory { public Message createMessage(GroupId g, long timestamp, byte[] body) { if (body.length > MAX_MESSAGE_BODY_LENGTH) throw new IllegalArgumentException(); - byte[] versionBytes = new byte[] {FORMAT_VERSION}; - // There's only one block, so the root hash is the hash of the block - byte[] rootHash = crypto.hash(BLOCK_LABEL, versionBytes, body); - byte[] timeBytes = new byte[INT_64_BYTES]; - ByteUtils.writeUint64(timestamp, timeBytes, 0); - byte[] idHash = crypto.hash(ID_LABEL, versionBytes, g.getBytes(), - timeBytes, rootHash); - MessageId id = new MessageId(idHash); + MessageId id = getMessageId(g, timestamp, body); byte[] raw = new byte[MESSAGE_HEADER_LENGTH + body.length]; System.arraycopy(g.getBytes(), 0, raw, 0, UniqueId.LENGTH); ByteUtils.writeUint64(timestamp, raw, UniqueId.LENGTH); @@ -50,6 +46,32 @@ class MessageFactoryImpl implements MessageFactory { return new Message(id, g, timestamp, raw); } + private MessageId getMessageId(GroupId g, long timestamp, byte[] body) { + // There's only one block, so the root hash is the hash of the block + byte[] rootHash = crypto.hash(BLOCK_LABEL, FORMAT_VERSION_BYTES, body); + byte[] timeBytes = new byte[INT_64_BYTES]; + ByteUtils.writeUint64(timestamp, timeBytes, 0); + byte[] idHash = crypto.hash(ID_LABEL, FORMAT_VERSION_BYTES, + g.getBytes(), timeBytes, rootHash); + return new MessageId(idHash); + } + + @Override + public Message createMessage(byte[] raw) { + if (raw.length < MESSAGE_HEADER_LENGTH) + throw new IllegalArgumentException(); + if (raw.length > MAX_MESSAGE_LENGTH) + throw new IllegalArgumentException(); + byte[] groupId = new byte[UniqueId.LENGTH]; + System.arraycopy(raw, 0, groupId, 0, UniqueId.LENGTH); + GroupId g = new GroupId(groupId); + long timestamp = ByteUtils.readUint64(raw, UniqueId.LENGTH); + byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH]; + System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length); + MessageId id = getMessageId(g, timestamp, body); + return new Message(id, g, timestamp, raw); + } + @Override public Message createMessage(MessageId m, byte[] raw) { if (raw.length < MESSAGE_HEADER_LENGTH) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java index d7566979d218dd1f7c595568c60a619ce6a26685..3a7c6d057bcf21b85fdde144626576ab3d4345cd 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java @@ -6,7 +6,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.record.Record; import org.briarproject.bramble.api.record.RecordReader; import org.briarproject.bramble.api.sync.Ack; -import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.MessageId; @@ -126,20 +125,11 @@ class SyncRecordReaderImpl implements SyncRecordReader { assert nextRecord != null; byte[] payload = nextRecord.getPayload(); if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException(); - // Group ID - byte[] id = new byte[UniqueId.LENGTH]; - System.arraycopy(payload, 0, id, 0, UniqueId.LENGTH); - GroupId groupId = new GroupId(id); - // Timestamp + // Validate timestamp long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH); if (timestamp < 0) throw new FormatException(); - // Body - byte[] body = new byte[payload.length - MESSAGE_HEADER_LENGTH]; - System.arraycopy(payload, MESSAGE_HEADER_LENGTH, body, 0, - payload.length - MESSAGE_HEADER_LENGTH); nextRecord = null; - // TODO: Add a method that reuses the raw message - return messageFactory.createMessage(groupId, timestamp, body); + return messageFactory.createMessage(payload); } @Override