Make it possible to deserialize SenderKeyDistributionMessages
This commit is contained in:
parent
aa1c41c980
commit
bf9c8708e0
|
@ -1,7 +1,12 @@
|
|||
package org.whispersystems.libaxolotl.protocol;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
import org.whispersystems.libaxolotl.LegacyMessageException;
|
||||
import org.whispersystems.libaxolotl.ecc.Curve;
|
||||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
||||
import org.whispersystems.libaxolotl.util.ByteUtil;
|
||||
|
||||
|
@ -15,17 +20,52 @@ public class SenderKeyDistributionMessage implements CiphertextMessage {
|
|||
|
||||
public SenderKeyDistributionMessage(int id, int iteration, byte[] chainKey, ECPublicKey signatureKey) {
|
||||
byte[] version = {ByteUtil.intsToByteHighAndLow(CURRENT_VERSION, CURRENT_VERSION)};
|
||||
byte[] protobuf = WhisperProtos.SenderKeyDistributionMessage.newBuilder()
|
||||
.setId(id)
|
||||
.setIteration(iteration)
|
||||
.setChainKey(ByteString.copyFrom(chainKey))
|
||||
.setSigningKey(ByteString.copyFrom(signatureKey.serialize()))
|
||||
.build().toByteArray();
|
||||
|
||||
this.id = id;
|
||||
this.iteration = iteration;
|
||||
this.chainKey = chainKey;
|
||||
this.signatureKey = signatureKey;
|
||||
this.serialized = WhisperProtos.SenderKeyDistributionMessage.newBuilder()
|
||||
.setId(id)
|
||||
.setIteration(iteration)
|
||||
.setChainKey(ByteString.copyFrom(chainKey))
|
||||
.setSigningKey(ByteString.copyFrom(signatureKey.serialize()))
|
||||
.build().toByteArray();
|
||||
this.serialized = ByteUtil.combine(version, protobuf);
|
||||
}
|
||||
|
||||
public SenderKeyDistributionMessage(byte[] serialized) throws LegacyMessageException, InvalidMessageException {
|
||||
try {
|
||||
byte[][] messageParts = ByteUtil.split(serialized, 1, serialized.length - 1);
|
||||
byte version = messageParts[0][0];
|
||||
byte[] message = messageParts[1];
|
||||
|
||||
if (ByteUtil.highBitsToInt(version) < CiphertextMessage.CURRENT_VERSION) {
|
||||
throw new LegacyMessageException("Legacy message: " + ByteUtil.highBitsToInt(version));
|
||||
}
|
||||
|
||||
if (ByteUtil.highBitsToInt(version) > CURRENT_VERSION) {
|
||||
throw new InvalidMessageException("Unknown version: " + ByteUtil.highBitsToInt(version));
|
||||
}
|
||||
|
||||
WhisperProtos.SenderKeyDistributionMessage distributionMessage = WhisperProtos.SenderKeyDistributionMessage.parseFrom(message);
|
||||
|
||||
if (!distributionMessage.hasId() ||
|
||||
!distributionMessage.hasIteration() ||
|
||||
!distributionMessage.hasChainKey() ||
|
||||
!distributionMessage.hasSigningKey())
|
||||
{
|
||||
throw new InvalidMessageException("Incomplete message.");
|
||||
}
|
||||
|
||||
this.serialized = serialized;
|
||||
this.id = distributionMessage.getId();
|
||||
this.iteration = distributionMessage.getIteration();
|
||||
this.chainKey = distributionMessage.getChainKey().toByteArray();
|
||||
this.signatureKey = Curve.decodePoint(distributionMessage.getSigningKey().toByteArray(), 0);
|
||||
} catch (InvalidProtocolBufferException | InvalidKeyException e) {
|
||||
throw new InvalidMessageException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,9 +30,9 @@ public class GroupCipherTest extends TestCase {
|
|||
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, GROUP_SENDER);
|
||||
GroupCipher bobGroupCipher = new GroupCipher(bobStore, GROUP_SENDER);
|
||||
|
||||
SenderKeyDistributionMessage aliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER);
|
||||
|
||||
bobSessionBuilder.process(GROUP_SENDER, aliceDistributionMessage);
|
||||
SenderKeyDistributionMessage sentAliceDistributionMessage = aliceSessionBuilder.create(GROUP_SENDER);
|
||||
SenderKeyDistributionMessage receivedAliceDistributionMessage = new SenderKeyDistributionMessage(sentAliceDistributionMessage.serialize());
|
||||
bobSessionBuilder.process(GROUP_SENDER, receivedAliceDistributionMessage);
|
||||
|
||||
byte[] ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert".getBytes());
|
||||
byte[] plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice);
|
||||
|
@ -54,10 +54,12 @@ public class GroupCipherTest extends TestCase {
|
|||
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, aliceName);
|
||||
GroupCipher bobGroupCipher = new GroupCipher(bobStore, aliceName);
|
||||
|
||||
SenderKeyDistributionMessage aliceDistributionMessage =
|
||||
SenderKeyDistributionMessage sentAliceDistributionMessage =
|
||||
aliceSessionBuilder.create(aliceName);
|
||||
SenderKeyDistributionMessage receivedAliceDistributionMessage =
|
||||
new SenderKeyDistributionMessage(sentAliceDistributionMessage.serialize());
|
||||
|
||||
bobSessionBuilder.process(aliceName, aliceDistributionMessage);
|
||||
bobSessionBuilder.process(aliceName, receivedAliceDistributionMessage);
|
||||
|
||||
byte[] ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert".getBytes());
|
||||
byte[] ciphertextFromAlice2 = aliceGroupCipher.encrypt("smert ze smert2".getBytes());
|
||||
|
@ -80,6 +82,40 @@ public class GroupCipherTest extends TestCase {
|
|||
assertTrue(new String(plaintextFromAlice3).equals("smert ze smert3"));
|
||||
}
|
||||
|
||||
public void testLateJoin() throws NoSessionException, InvalidMessageException, LegacyMessageException, DuplicateMessageException {
|
||||
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
|
||||
InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
|
||||
|
||||
GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
|
||||
|
||||
|
||||
SenderKeyName aliceName = GROUP_SENDER;
|
||||
|
||||
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, aliceName);
|
||||
|
||||
|
||||
SenderKeyDistributionMessage aliceDistributionMessage = aliceSessionBuilder.create(aliceName);
|
||||
// Send off to some people.
|
||||
|
||||
for (int i=0;i<100;i++) {
|
||||
aliceGroupCipher.encrypt("up the punks up the punks up the punks".getBytes());
|
||||
}
|
||||
|
||||
// Now Bob Joins.
|
||||
GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
|
||||
GroupCipher bobGroupCipher = new GroupCipher(bobStore, aliceName);
|
||||
|
||||
|
||||
SenderKeyDistributionMessage distributionMessageToBob = aliceSessionBuilder.create(aliceName);
|
||||
bobSessionBuilder.process(aliceName, new SenderKeyDistributionMessage(distributionMessageToBob.serialize()));
|
||||
|
||||
byte[] ciphertext = aliceGroupCipher.encrypt("welcome to the group".getBytes());
|
||||
byte[] plaintext = bobGroupCipher.decrypt(ciphertext);
|
||||
|
||||
assertEquals(new String(plaintext), "welcome to the group");
|
||||
}
|
||||
|
||||
|
||||
public void testOutOfOrder()
|
||||
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue