mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-11 18:31:51 +00:00
Add first cut of protocol v3 support.
1) Use the new /v2/keys API for storing/retrieving prekey bundles. 2) For sessions built with PreKeyBundle and PreKeyWhisperMessage, use a v3 ratcheting session when available.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package org.whispersystems.test;
|
||||
|
||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
||||
import org.whispersystems.libaxolotl.state.DeviceKeyRecord;
|
||||
import org.whispersystems.libaxolotl.state.DeviceKeyStore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class InMemoryDeviceKeyStore implements DeviceKeyStore {
|
||||
|
||||
private final Map<Integer, byte[]> store = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public DeviceKeyRecord loadDeviceKey(int deviceKeyId) throws InvalidKeyIdException {
|
||||
try {
|
||||
if (!store.containsKey(deviceKeyId)) {
|
||||
throw new InvalidKeyIdException("No such devicekeyrecord!");
|
||||
}
|
||||
|
||||
return new DeviceKeyRecord(store.get(deviceKeyId));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<DeviceKeyRecord> loadDeviceKeys() {
|
||||
try {
|
||||
List<DeviceKeyRecord> results = new LinkedList<>();
|
||||
|
||||
for (byte[] serialized : store.values()) {
|
||||
results.add(new DeviceKeyRecord(serialized));
|
||||
}
|
||||
|
||||
return results;
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeDeviceKey(int deviceKeyId, DeviceKeyRecord record) {
|
||||
store.put(deviceKeyId, record.serialize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsDeviceKey(int deviceKeyId) {
|
||||
return store.containsKey(deviceKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDeviceKey(int deviceKeyId) {
|
||||
store.remove(deviceKeyId);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class InMemoryPreKeyStore implements PreKeyStore {
|
||||
private final Map<Integer, byte[]> store = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public PreKeyRecord load(int preKeyId) throws InvalidKeyIdException {
|
||||
public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException {
|
||||
try {
|
||||
if (!store.containsKey(preKeyId)) {
|
||||
throw new InvalidKeyIdException("No such prekeyrecord!");
|
||||
@@ -26,17 +26,17 @@ public class InMemoryPreKeyStore implements PreKeyStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(int preKeyId, PreKeyRecord record) {
|
||||
public void storePreKey(int preKeyId, PreKeyRecord record) {
|
||||
store.put(preKeyId, record.serialize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int preKeyId) {
|
||||
public boolean containsPreKey(int preKeyId) {
|
||||
return store.containsKey(preKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(int preKeyId) {
|
||||
public void removePreKey(int preKeyId) {
|
||||
store.remove(preKeyId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ public class InMemorySessionStore implements SessionStore {
|
||||
public InMemorySessionStore() {}
|
||||
|
||||
@Override
|
||||
public synchronized SessionRecord load(long recipientId, int deviceId) {
|
||||
public synchronized SessionRecord loadSession(long recipientId, int deviceId) {
|
||||
try {
|
||||
if (contains(recipientId, deviceId)) {
|
||||
if (containsSession(recipientId, deviceId)) {
|
||||
return new SessionRecord(sessions.get(new Pair<>(recipientId, deviceId)));
|
||||
} else {
|
||||
return new SessionRecord();
|
||||
@@ -43,22 +43,22 @@ public class InMemorySessionStore implements SessionStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void store(long recipientId, int deviceId, SessionRecord record) {
|
||||
public synchronized void storeSession(long recipientId, int deviceId, SessionRecord record) {
|
||||
sessions.put(new Pair<>(recipientId, deviceId), record.serialize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean contains(long recipientId, int deviceId) {
|
||||
public synchronized boolean containsSession(long recipientId, int deviceId) {
|
||||
return sessions.containsKey(new Pair<>(recipientId, deviceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void delete(long recipientId, int deviceId) {
|
||||
public synchronized void deleteSession(long recipientId, int deviceId) {
|
||||
sessions.remove(new Pair<>(recipientId, deviceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deleteAll(long recipientId) {
|
||||
public synchronized void deleteAllSessions(long recipientId) {
|
||||
for (Pair<Long, Integer> key : sessions.keySet()) {
|
||||
if (key.first() == recipientId) {
|
||||
sessions.remove(key);
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.whispersystems.test;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import org.whispersystems.libaxolotl.DuplicateMessageException;
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
@@ -15,12 +14,13 @@ import org.whispersystems.libaxolotl.StaleKeyExchangeException;
|
||||
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
||||
import org.whispersystems.libaxolotl.ecc.Curve;
|
||||
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
|
||||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
||||
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
|
||||
import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
|
||||
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
|
||||
import org.whispersystems.libaxolotl.state.DeviceKeyRecord;
|
||||
import org.whispersystems.libaxolotl.state.DeviceKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.IdentityKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.PreKey;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyBundle;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
||||
import org.whispersystems.libaxolotl.state.PreKeyStore;
|
||||
import org.whispersystems.libaxolotl.state.SessionStore;
|
||||
@@ -34,30 +34,37 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
private static final long ALICE_RECIPIENT_ID = 5L;
|
||||
private static final long BOB_RECIPIENT_ID = 2L;
|
||||
|
||||
public void testBasicPreKey()
|
||||
public void testBasicPreKeyV2()
|
||||
throws InvalidKeyException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, UntrustedIdentityException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore bobPreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore bobDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder bobSessionBuilder = new SessionBuilder(bobSessionStore, bobPreKeyStore,
|
||||
bobDeviceKeyStore,
|
||||
bobIdentityKeyStore,
|
||||
ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
InMemoryPreKey bobPreKey = new InMemoryPreKey(31337, Curve.generateKeyPair(true),
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey(),
|
||||
bobIdentityKeyStore.getLocalRegistrationId());
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
0, null, null,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
|
||||
assertTrue(aliceSessionStore.contains(BOB_RECIPIENT_ID, 1));
|
||||
assertTrue(!aliceSessionStore.load(BOB_RECIPIENT_ID, 1).getSessionState().getNeedsRefresh());
|
||||
assertTrue(aliceSessionStore.containsSession(BOB_RECIPIENT_ID, 1));
|
||||
assertTrue(!aliceSessionStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getNeedsRefresh());
|
||||
assertTrue(aliceSessionStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 2);
|
||||
|
||||
String originalMessage = "L'homme est condamné à être libre";
|
||||
SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, BOB_RECIPIENT_ID, 1);
|
||||
@@ -66,10 +73,11 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||
|
||||
PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessage.serialize());
|
||||
bobPreKeyStore.store(31337, bobPreKey);
|
||||
bobPreKeyStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
|
||||
bobSessionBuilder.process(incomingMessage);
|
||||
|
||||
assertTrue(bobSessionStore.contains(ALICE_RECIPIENT_ID, 1));
|
||||
assertTrue(bobSessionStore.containsSession(ALICE_RECIPIENT_ID, 1));
|
||||
assertTrue(bobSessionStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 2);
|
||||
|
||||
SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, ALICE_RECIPIENT_ID, 1);
|
||||
byte[] plaintext = bobSessionCipher.decrypt(incomingMessage.getWhisperMessage().serialize());
|
||||
@@ -87,15 +95,17 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
aliceSessionStore = new InMemorySessionStore();
|
||||
aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
aliceSessionCipher = new SessionCipher(aliceSessionStore, BOB_RECIPIENT_ID, 1);
|
||||
|
||||
bobPreKey = new InMemoryPreKey(31338, Curve.generateKeyPair(true),
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey(),
|
||||
bobIdentityKeyStore.getLocalRegistrationId());
|
||||
bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(),
|
||||
1, 31338, bobPreKeyPair.getPublicKey(),
|
||||
0, null, null, bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
bobPreKeyStore.store(31338, bobPreKey);
|
||||
bobPreKeyStore.storePreKey(31338, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
|
||||
outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
@@ -111,9 +121,10 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize()).getWhisperMessage().serialize());
|
||||
assertTrue(new String(plaintext).equals(originalMessage));
|
||||
|
||||
bobPreKey = new InMemoryPreKey(31337, Curve.generateKeyPair(true),
|
||||
aliceIdentityKeyStore.getIdentityKeyPair().getPublicKey(),
|
||||
bobIdentityKeyStore.getLocalRegistrationId());
|
||||
bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, Curve.generateKeyPair(true).getPublicKey(),
|
||||
0, null, null,
|
||||
aliceIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
try {
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
@@ -123,18 +134,315 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testBasicKeyExchange() throws InvalidKeyException, LegacyMessageException, InvalidMessageException, DuplicateMessageException, UntrustedIdentityException, StaleKeyExchangeException {
|
||||
public void testBasicPreKeyV3()
|
||||
throws InvalidKeyException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, UntrustedIdentityException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore bobPreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore bobDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder bobSessionBuilder = new SessionBuilder(bobSessionStore, bobPreKeyStore,
|
||||
bobDeviceKeyStore,
|
||||
bobIdentityKeyStore,
|
||||
ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
ECKeyPair bobDeviceKeyPair = Curve.generateKeyPair(true);
|
||||
byte[] bobDeviceKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
|
||||
bobDeviceKeyPair.getPublicKey().serialize());
|
||||
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
22, bobDeviceKeyPair.getPublicKey(), bobDeviceKeySignature,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
|
||||
assertTrue(aliceSessionStore.containsSession(BOB_RECIPIENT_ID, 1));
|
||||
assertTrue(!aliceSessionStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getNeedsRefresh());
|
||||
assertTrue(aliceSessionStore.loadSession(BOB_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
|
||||
|
||||
String originalMessage = "L'homme est condamné à être libre";
|
||||
SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, BOB_RECIPIENT_ID, 1);
|
||||
CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||
|
||||
PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessage.serialize());
|
||||
bobPreKeyStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
|
||||
bobDeviceKeyStore.storeDeviceKey(22, new DeviceKeyRecord(22, System.currentTimeMillis(), bobDeviceKeyPair, bobDeviceKeySignature));
|
||||
bobSessionBuilder.process(incomingMessage);
|
||||
|
||||
assertTrue(bobSessionStore.containsSession(ALICE_RECIPIENT_ID, 1));
|
||||
assertTrue(bobSessionStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getSessionVersion() == 3);
|
||||
assertTrue(bobSessionStore.loadSession(ALICE_RECIPIENT_ID, 1).getSessionState().getAliceBaseKey() != null);
|
||||
|
||||
SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, ALICE_RECIPIENT_ID, 1);
|
||||
byte[] plaintext = bobSessionCipher.decrypt(incomingMessage.getWhisperMessage().serialize());
|
||||
|
||||
assertTrue(originalMessage.equals(new String(plaintext)));
|
||||
|
||||
CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
|
||||
assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE);
|
||||
|
||||
byte[] alicePlaintext = aliceSessionCipher.decrypt(bobOutgoingMessage.serialize());
|
||||
assertTrue(new String(alicePlaintext).equals(originalMessage));
|
||||
|
||||
runInteraction(aliceSessionStore, bobSessionStore);
|
||||
|
||||
aliceSessionStore = new InMemorySessionStore();
|
||||
aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
aliceSessionCipher = new SessionCipher(aliceSessionStore, BOB_RECIPIENT_ID, 1);
|
||||
|
||||
bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
bobDeviceKeyPair = Curve.generateKeyPair(true);
|
||||
bobDeviceKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(), bobDeviceKeyPair.getPublicKey().serialize());
|
||||
bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(),
|
||||
1, 31338, bobPreKeyPair.getPublicKey(),
|
||||
23, bobDeviceKeyPair.getPublicKey(), bobDeviceKeySignature,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
bobPreKeyStore.storePreKey(31338, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
|
||||
bobDeviceKeyStore.storeDeviceKey(23, new DeviceKeyRecord(23, System.currentTimeMillis(), bobDeviceKeyPair, bobDeviceKeySignature));
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
|
||||
outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
try {
|
||||
bobSessionBuilder.process(new PreKeyWhisperMessage(outgoingMessage.serialize()));
|
||||
throw new AssertionError("shouldn't be trusted!");
|
||||
} catch (UntrustedIdentityException uie) {
|
||||
bobIdentityKeyStore.saveIdentity(ALICE_RECIPIENT_ID, new PreKeyWhisperMessage(outgoingMessage.serialize()).getIdentityKey());
|
||||
bobSessionBuilder.process(new PreKeyWhisperMessage(outgoingMessage.serialize()));
|
||||
}
|
||||
|
||||
plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize()).getWhisperMessage().serialize());
|
||||
assertTrue(new String(plaintext).equals(originalMessage));
|
||||
|
||||
bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, Curve.generateKeyPair(true).getPublicKey(),
|
||||
23, bobDeviceKeyPair.getPublicKey(), bobDeviceKeySignature,
|
||||
aliceIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
try {
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
throw new AssertionError("shoulnd't be trusted!");
|
||||
} catch (UntrustedIdentityException uie) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
|
||||
public void testBadDeviceKeySignature() throws InvalidKeyException, UntrustedIdentityException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
ECKeyPair bobDeviceKeyPair = Curve.generateKeyPair(true);
|
||||
byte[] bobDeviceKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
|
||||
bobDeviceKeyPair.getPublicKey().serialize());
|
||||
|
||||
|
||||
for (int i=0;i<bobDeviceKeySignature.length * 8;i++) {
|
||||
byte[] modifiedSignature = new byte[bobDeviceKeySignature.length];
|
||||
System.arraycopy(bobDeviceKeySignature, 0, modifiedSignature, 0, modifiedSignature.length);
|
||||
|
||||
modifiedSignature[i/8] ^= (0x01 << (i % 8));
|
||||
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
22, bobDeviceKeyPair.getPublicKey(), modifiedSignature,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
try {
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
throw new AssertionError("Accepted modified device key signature!");
|
||||
} catch (InvalidKeyException ike) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
22, bobDeviceKeyPair.getPublicKey(), bobDeviceKeySignature,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
}
|
||||
|
||||
public void testRepeatBundleMessageV2() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore bobPreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore bobDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder bobSessionBuilder = new SessionBuilder(bobSessionStore, bobPreKeyStore,
|
||||
bobDeviceKeyStore,
|
||||
bobIdentityKeyStore,
|
||||
ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
ECKeyPair bobDeviceKeyPair = Curve.generateKeyPair(true);
|
||||
byte[] bobDeviceKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
|
||||
bobDeviceKeyPair.getPublicKey().serialize());
|
||||
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
0, null, null,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
bobPreKeyStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
|
||||
bobDeviceKeyStore.storeDeviceKey(22, new DeviceKeyRecord(22, System.currentTimeMillis(), bobDeviceKeyPair, bobDeviceKeySignature));
|
||||
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
|
||||
String originalMessage = "L'homme est condamné à être libre";
|
||||
SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, BOB_RECIPIENT_ID, 1);
|
||||
CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
CiphertextMessage outgoingMessageTwo = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
assertTrue(outgoingMessageOne.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||
|
||||
PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessageOne.serialize());
|
||||
bobSessionBuilder.process(incomingMessage);
|
||||
|
||||
SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
byte[] plaintext = bobSessionCipher.decrypt(incomingMessage.getWhisperMessage().serialize());
|
||||
assertTrue(originalMessage.equals(new String(plaintext)));
|
||||
|
||||
CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
byte[] alicePlaintext = aliceSessionCipher.decrypt(bobOutgoingMessage.serialize());
|
||||
assertTrue(originalMessage.equals(new String(alicePlaintext)));
|
||||
|
||||
// The test
|
||||
|
||||
PreKeyWhisperMessage incomingMessageTwo = new PreKeyWhisperMessage(outgoingMessageTwo.serialize());
|
||||
bobSessionBuilder.process(incomingMessageTwo);
|
||||
|
||||
plaintext = bobSessionCipher.decrypt(incomingMessageTwo.getWhisperMessage().serialize());
|
||||
assertTrue(originalMessage.equals(new String(plaintext)));
|
||||
|
||||
bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
|
||||
alicePlaintext = aliceSessionCipher.decrypt(bobOutgoingMessage.serialize());
|
||||
assertTrue(originalMessage.equals(new String(alicePlaintext)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testRepeatBundleMessageV3() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore bobPreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore bobDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder bobSessionBuilder = new SessionBuilder(bobSessionStore, bobPreKeyStore,
|
||||
bobDeviceKeyStore,
|
||||
bobIdentityKeyStore,
|
||||
ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
ECKeyPair bobPreKeyPair = Curve.generateKeyPair(true);
|
||||
ECKeyPair bobDeviceKeyPair = Curve.generateKeyPair(true);
|
||||
byte[] bobDeviceKeySignature = Curve.calculateSignature(bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
|
||||
bobDeviceKeyPair.getPublicKey().serialize());
|
||||
|
||||
PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.getLocalRegistrationId(), 1,
|
||||
31337, bobPreKeyPair.getPublicKey(),
|
||||
22, bobDeviceKeyPair.getPublicKey(), bobDeviceKeySignature,
|
||||
bobIdentityKeyStore.getIdentityKeyPair().getPublicKey());
|
||||
|
||||
bobPreKeyStore.storePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair));
|
||||
bobDeviceKeyStore.storeDeviceKey(22, new DeviceKeyRecord(22, System.currentTimeMillis(), bobDeviceKeyPair, bobDeviceKeySignature));
|
||||
|
||||
aliceSessionBuilder.process(bobPreKey);
|
||||
|
||||
String originalMessage = "L'homme est condamné à être libre";
|
||||
SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, BOB_RECIPIENT_ID, 1);
|
||||
CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
CiphertextMessage outgoingMessageTwo = aliceSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
assertTrue(outgoingMessageOne.getType() == CiphertextMessage.PREKEY_TYPE);
|
||||
|
||||
PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessageOne.serialize());
|
||||
bobSessionBuilder.process(incomingMessage);
|
||||
|
||||
SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
byte[] plaintext = bobSessionCipher.decrypt(incomingMessage.getWhisperMessage().serialize());
|
||||
assertTrue(originalMessage.equals(new String(plaintext)));
|
||||
|
||||
CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
|
||||
|
||||
byte[] alicePlaintext = aliceSessionCipher.decrypt(bobOutgoingMessage.serialize());
|
||||
assertTrue(originalMessage.equals(new String(alicePlaintext)));
|
||||
|
||||
// The test
|
||||
|
||||
PreKeyWhisperMessage incomingMessageTwo = new PreKeyWhisperMessage(outgoingMessageTwo.serialize());
|
||||
bobSessionBuilder.process(incomingMessageTwo);
|
||||
|
||||
plaintext = bobSessionCipher.decrypt(incomingMessageTwo.getWhisperMessage().serialize());
|
||||
assertTrue(originalMessage.equals(new String(plaintext)));
|
||||
|
||||
bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
|
||||
alicePlaintext = aliceSessionCipher.decrypt(bobOutgoingMessage.serialize());
|
||||
assertTrue(originalMessage.equals(new String(alicePlaintext)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testBasicKeyExchange() throws InvalidKeyException, LegacyMessageException, InvalidMessageException, DuplicateMessageException, UntrustedIdentityException, StaleKeyExchangeException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore bobPreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore bobDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder bobSessionBuilder = new SessionBuilder(bobSessionStore, bobPreKeyStore,
|
||||
bobDeviceKeyStore,
|
||||
bobIdentityKeyStore,
|
||||
ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
@@ -147,14 +455,15 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
KeyExchangeMessage response = aliceSessionBuilder.process(bobKeyExchangeMessage);
|
||||
|
||||
assertTrue(response == null);
|
||||
assertTrue(aliceSessionStore.contains(BOB_RECIPIENT_ID, 1));
|
||||
assertTrue(bobSessionStore.contains(ALICE_RECIPIENT_ID, 1));
|
||||
assertTrue(aliceSessionStore.containsSession(BOB_RECIPIENT_ID, 1));
|
||||
assertTrue(bobSessionStore.containsSession(ALICE_RECIPIENT_ID, 1));
|
||||
|
||||
runInteraction(aliceSessionStore, bobSessionStore);
|
||||
|
||||
aliceSessionStore = new InMemorySessionStore();
|
||||
aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore, BOB_RECIPIENT_ID, 1);
|
||||
aliceKeyExchangeMessage = aliceSessionBuilder.process();
|
||||
|
||||
@@ -175,15 +484,19 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
throws InvalidKeyException, DuplicateMessageException, LegacyMessageException, InvalidMessageException, UntrustedIdentityException, StaleKeyExchangeException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore aliceDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore aliceIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
|
||||
aliceDeviceKeyStore,
|
||||
aliceIdentityKeyStore,
|
||||
BOB_RECIPIENT_ID, 1);
|
||||
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
PreKeyStore bobPreKeyStore = new InMemoryPreKeyStore();
|
||||
DeviceKeyStore bobDeviceKeyStore = new InMemoryDeviceKeyStore();
|
||||
IdentityKeyStore bobIdentityKeyStore = new InMemoryIdentityKeyStore();
|
||||
SessionBuilder bobSessionBuilder = new SessionBuilder(bobSessionStore, bobPreKeyStore,
|
||||
bobDeviceKeyStore,
|
||||
bobIdentityKeyStore,
|
||||
ALICE_RECIPIENT_ID, 1);
|
||||
|
||||
@@ -284,41 +597,5 @@ public class SessionBuilderTest extends AndroidTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private class InMemoryPreKey extends PreKeyRecord implements PreKey {
|
||||
|
||||
private final IdentityKey identityKey;
|
||||
private final int registrationId;
|
||||
|
||||
public InMemoryPreKey(int keyId, ECKeyPair keyPair, IdentityKey identityKey, int registrationId) {
|
||||
super(keyId, keyPair);
|
||||
this.identityKey = identityKey;
|
||||
this.registrationId = registrationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeviceId() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getKeyId() {
|
||||
return getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ECPublicKey getPublicKey() {
|
||||
return getKeyPair().getPublicKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityKey getIdentityKey() {
|
||||
return identityKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegistrationId() {
|
||||
return registrationId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,32 +9,53 @@ import org.whispersystems.libaxolotl.InvalidKeyException;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
import org.whispersystems.libaxolotl.LegacyMessageException;
|
||||
import org.whispersystems.libaxolotl.SessionCipher;
|
||||
import org.whispersystems.libaxolotl.state.SessionRecord;
|
||||
import org.whispersystems.libaxolotl.state.SessionState;
|
||||
import org.whispersystems.libaxolotl.state.SessionStore;
|
||||
import org.whispersystems.libaxolotl.ecc.Curve;
|
||||
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
|
||||
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
|
||||
import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
|
||||
import org.whispersystems.libaxolotl.ratchet.RatchetingSessionV2;
|
||||
import org.whispersystems.libaxolotl.ratchet.RatchetingSessionV3;
|
||||
import org.whispersystems.libaxolotl.state.SessionRecord;
|
||||
import org.whispersystems.libaxolotl.state.SessionState;
|
||||
import org.whispersystems.libaxolotl.state.SessionStore;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class SessionCipherTest extends AndroidTestCase {
|
||||
|
||||
public void testBasicSession()
|
||||
public void testBasicSessionV2()
|
||||
throws InvalidKeyException, DuplicateMessageException,
|
||||
LegacyMessageException, InvalidMessageException
|
||||
LegacyMessageException, InvalidMessageException, NoSuchAlgorithmException
|
||||
{
|
||||
SessionRecord aliceSessionRecord = new SessionRecord();
|
||||
SessionRecord bobSessionRecord = new SessionRecord();
|
||||
|
||||
initializeSessions(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState());
|
||||
initializeSessionsV2(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState());
|
||||
runInteraction(aliceSessionRecord, bobSessionRecord);
|
||||
}
|
||||
|
||||
public void testBasicSessionV3()
|
||||
throws InvalidKeyException, DuplicateMessageException,
|
||||
LegacyMessageException, InvalidMessageException, NoSuchAlgorithmException
|
||||
{
|
||||
SessionRecord aliceSessionRecord = new SessionRecord();
|
||||
SessionRecord bobSessionRecord = new SessionRecord();
|
||||
|
||||
initializeSessionsV3(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState());
|
||||
runInteraction(aliceSessionRecord, bobSessionRecord);
|
||||
}
|
||||
|
||||
private void runInteraction(SessionRecord aliceSessionRecord, SessionRecord bobSessionRecord)
|
||||
throws DuplicateMessageException, LegacyMessageException, InvalidMessageException, NoSuchAlgorithmException {
|
||||
SessionStore aliceSessionStore = new InMemorySessionStore();
|
||||
SessionStore bobSessionStore = new InMemorySessionStore();
|
||||
|
||||
aliceSessionStore.store(2L, 1, aliceSessionRecord);
|
||||
bobSessionStore.store(3L, 1, bobSessionRecord);
|
||||
aliceSessionStore.storeSession(2L, 1, aliceSessionRecord);
|
||||
bobSessionStore.storeSession(3L, 1, bobSessionRecord);
|
||||
|
||||
SessionCipher aliceCipher = new SessionCipher(aliceSessionStore, 2L, 1);
|
||||
SessionCipher bobCipher = new SessionCipher(bobSessionStore, 3L, 1);
|
||||
@@ -50,10 +71,56 @@ public class SessionCipherTest extends AndroidTestCase {
|
||||
byte[] receivedReply = aliceCipher.decrypt(reply.serialize());
|
||||
|
||||
assertTrue(Arrays.equals(bobReply, receivedReply));
|
||||
|
||||
List<CiphertextMessage> aliceCiphertextMessages = new ArrayList<>();
|
||||
List<byte[]> alicePlaintextMessages = new ArrayList<>();
|
||||
|
||||
for (int i=0;i<50;i++) {
|
||||
alicePlaintextMessages.add(("смерть за смерть " + i).getBytes());
|
||||
aliceCiphertextMessages.add(aliceCipher.encrypt(("смерть за смерть " + i).getBytes()));
|
||||
}
|
||||
|
||||
long seed = System.currentTimeMillis();
|
||||
|
||||
Collections.shuffle(aliceCiphertextMessages, new Random(seed));
|
||||
Collections.shuffle(alicePlaintextMessages, new Random(seed));
|
||||
|
||||
for (int i=0;i<aliceCiphertextMessages.size() / 2;i++) {
|
||||
byte[] receivedPlaintext = bobCipher.decrypt(aliceCiphertextMessages.get(i).serialize());
|
||||
assertTrue(Arrays.equals(receivedPlaintext, alicePlaintextMessages.get(i)));
|
||||
}
|
||||
|
||||
List<CiphertextMessage> bobCiphertextMessages = new ArrayList<>();
|
||||
List<byte[]> bobPlaintextMessages = new ArrayList<>();
|
||||
|
||||
for (int i=0;i<20;i++) {
|
||||
bobPlaintextMessages.add(("смерть за смерть " + i).getBytes());
|
||||
bobCiphertextMessages.add(bobCipher.encrypt(("смерть за смерть " + i).getBytes()));
|
||||
}
|
||||
|
||||
seed = System.currentTimeMillis();
|
||||
|
||||
Collections.shuffle(bobCiphertextMessages, new Random(seed));
|
||||
Collections.shuffle(bobPlaintextMessages, new Random(seed));
|
||||
|
||||
for (int i=0;i<bobCiphertextMessages.size() / 2;i++) {
|
||||
byte[] receivedPlaintext = aliceCipher.decrypt(bobCiphertextMessages.get(i).serialize());
|
||||
assertTrue(Arrays.equals(receivedPlaintext, bobPlaintextMessages.get(i)));
|
||||
}
|
||||
|
||||
for (int i=aliceCiphertextMessages.size()/2;i<aliceCiphertextMessages.size();i++) {
|
||||
byte[] receivedPlaintext = bobCipher.decrypt(aliceCiphertextMessages.get(i).serialize());
|
||||
assertTrue(Arrays.equals(receivedPlaintext, alicePlaintextMessages.get(i)));
|
||||
}
|
||||
|
||||
for (int i=bobCiphertextMessages.size() / 2;i<bobCiphertextMessages.size();i++) {
|
||||
byte[] receivedPlaintext = aliceCipher.decrypt(bobCiphertextMessages.get(i).serialize());
|
||||
assertTrue(Arrays.equals(receivedPlaintext, bobPlaintextMessages.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeSessions(SessionState aliceSessionState, SessionState bobSessionState)
|
||||
private void initializeSessionsV2(SessionState aliceSessionState, SessionState bobSessionState)
|
||||
throws InvalidKeyException
|
||||
{
|
||||
ECKeyPair aliceIdentityKeyPair = Curve.generateKeyPair(false);
|
||||
@@ -69,12 +136,44 @@ public class SessionCipherTest extends AndroidTestCase {
|
||||
ECKeyPair bobEphemeralKey = bobBaseKey;
|
||||
|
||||
|
||||
RatchetingSession.initializeSession(aliceSessionState, aliceBaseKey, bobBaseKey.getPublicKey(),
|
||||
aliceEphemeralKey, bobEphemeralKey.getPublicKey(),
|
||||
aliceIdentityKey, bobIdentityKey.getPublicKey());
|
||||
RatchetingSessionV2.initializeSession(aliceSessionState, aliceBaseKey, bobBaseKey.getPublicKey(),
|
||||
aliceEphemeralKey, bobEphemeralKey.getPublicKey(),
|
||||
aliceIdentityKey, bobIdentityKey.getPublicKey());
|
||||
|
||||
RatchetingSessionV2.initializeSession(bobSessionState, bobBaseKey, aliceBaseKey.getPublicKey(),
|
||||
bobEphemeralKey, aliceEphemeralKey.getPublicKey(),
|
||||
bobIdentityKey, aliceIdentityKey.getPublicKey());
|
||||
}
|
||||
|
||||
private void initializeSessionsV3(SessionState aliceSessionState, SessionState bobSessionState)
|
||||
throws InvalidKeyException
|
||||
{
|
||||
ECKeyPair aliceIdentityKeyPair = Curve.generateKeyPair(false);
|
||||
IdentityKeyPair aliceIdentityKey = new IdentityKeyPair(new IdentityKey(aliceIdentityKeyPair.getPublicKey()),
|
||||
aliceIdentityKeyPair.getPrivateKey());
|
||||
ECKeyPair aliceBaseKey = Curve.generateKeyPair(true);
|
||||
ECKeyPair aliceEphemeralKey = Curve.generateKeyPair(true);
|
||||
|
||||
ECKeyPair alicePreKey = aliceBaseKey;
|
||||
|
||||
ECKeyPair bobIdentityKeyPair = Curve.generateKeyPair(false);
|
||||
IdentityKeyPair bobIdentityKey = new IdentityKeyPair(new IdentityKey(bobIdentityKeyPair.getPublicKey()),
|
||||
bobIdentityKeyPair.getPrivateKey());
|
||||
ECKeyPair bobBaseKey = Curve.generateKeyPair(true);
|
||||
ECKeyPair bobEphemeralKey = bobBaseKey;
|
||||
|
||||
ECKeyPair bobPreKey = Curve.generateKeyPair(true);
|
||||
|
||||
|
||||
RatchetingSessionV3.initializeSession(aliceSessionState, aliceBaseKey, bobBaseKey.getPublicKey(),
|
||||
aliceEphemeralKey, bobEphemeralKey.getPublicKey(),
|
||||
alicePreKey, bobPreKey.getPublicKey(),
|
||||
aliceIdentityKey, bobIdentityKey.getPublicKey());
|
||||
|
||||
RatchetingSessionV3.initializeSession(bobSessionState, bobBaseKey, aliceBaseKey.getPublicKey(),
|
||||
bobEphemeralKey, aliceEphemeralKey.getPublicKey(),
|
||||
bobPreKey, alicePreKey.getPublicKey(),
|
||||
bobIdentityKey, aliceIdentityKey.getPublicKey());
|
||||
|
||||
RatchetingSession.initializeSession(bobSessionState, bobBaseKey, aliceBaseKey.getPublicKey(),
|
||||
bobEphemeralKey, aliceEphemeralKey.getPublicKey(),
|
||||
bobIdentityKey, aliceIdentityKey.getPublicKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import org.whispersystems.libaxolotl.ecc.Curve;
|
||||
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
|
||||
import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
|
||||
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
|
||||
import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
|
||||
import org.whispersystems.libaxolotl.ratchet.RatchetingSessionV2;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class RatchetingSessionTest extends AndroidTestCase {
|
||||
public class RatchetingSessionV2Test extends AndroidTestCase {
|
||||
|
||||
public void testRatchetingSessionAsBob() throws InvalidKeyException {
|
||||
byte[] bobPublic = {(byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97,
|
||||
@@ -107,9 +107,9 @@ public class RatchetingSessionTest extends AndroidTestCase {
|
||||
|
||||
SessionState session = new SessionState();
|
||||
|
||||
RatchetingSession.initializeSession(session, bobBaseKey, aliceBasePublicKey,
|
||||
bobEphemeralKey, aliceEphemeralPublicKey,
|
||||
bobIdentityKey, aliceIdentityPublicKey);
|
||||
RatchetingSessionV2.initializeSession(session, bobBaseKey, aliceBasePublicKey,
|
||||
bobEphemeralKey, aliceEphemeralPublicKey,
|
||||
bobIdentityKey, aliceIdentityPublicKey);
|
||||
|
||||
assertTrue(session.getLocalIdentityKey().equals(bobIdentityKey.getPublicKey()));
|
||||
assertTrue(session.getRemoteIdentityKey().equals(aliceIdentityPublicKey));
|
||||
@@ -204,9 +204,9 @@ public class RatchetingSessionTest extends AndroidTestCase {
|
||||
|
||||
SessionState session = new SessionState();
|
||||
|
||||
RatchetingSession.initializeSession(session, aliceBaseKey, bobBasePublicKey,
|
||||
aliceEphemeralKey, bobEphemeralPublicKey,
|
||||
aliceIdentityKey, bobIdentityKey);
|
||||
RatchetingSessionV2.initializeSession(session, aliceBaseKey, bobBasePublicKey,
|
||||
aliceEphemeralKey, bobEphemeralPublicKey,
|
||||
aliceIdentityKey, bobIdentityKey);
|
||||
|
||||
assertTrue(session.getLocalIdentityKey().equals(aliceIdentityKey.getPublicKey()));
|
||||
assertTrue(session.getRemoteIdentityKey().equals(bobIdentityKey));
|
||||
Reference in New Issue
Block a user