diff options
Diffstat (limited to 'src/androidTest/java/org/whispersystems/test/groups')
-rw-r--r-- | src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java | 151 | ||||
-rw-r--r-- | src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java | 33 |
2 files changed, 184 insertions, 0 deletions
diff --git a/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java b/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java new file mode 100644 index 00000000..6d93e921 --- /dev/null +++ b/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java @@ -0,0 +1,151 @@ +package org.whispersystems.test.groups; + +import android.test.AndroidTestCase; +import android.util.Log; + +import org.whispersystems.libaxolotl.DuplicateMessageException; +import org.whispersystems.libaxolotl.InvalidMessageException; +import org.whispersystems.libaxolotl.LegacyMessageException; +import org.whispersystems.libaxolotl.NoSessionException; +import org.whispersystems.libaxolotl.ecc.ECKeyPair; +import org.whispersystems.libaxolotl.groups.GroupCipher; +import org.whispersystems.libaxolotl.groups.GroupSessionBuilder; +import org.whispersystems.libaxolotl.protocol.SenderKeyDistributionMessage; +import org.whispersystems.libaxolotl.util.KeyHelper; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class GroupCipherTest extends AndroidTestCase { + + public void testBasicEncryptDecrypt() + throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException + { + InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); + InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore(); + + GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore); + GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore); + + GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt"); + GroupCipher bobGroupCipher = new GroupCipher(bobStore, "groupWithBobInIt::aliceUserName"); + + byte[] aliceSenderKey = KeyHelper.generateSenderKey(); + ECKeyPair aliceSenderSigningKey = KeyHelper.generateSenderSigningKey(); + int aliceSenderKeyId = KeyHelper.generateSenderKeyId(); + + SenderKeyDistributionMessage aliceDistributionMessage = + aliceSessionBuilder.process("groupWithBobInIt", aliceSenderKeyId, 0, + aliceSenderKey, aliceSenderSigningKey); + + bobSessionBuilder.process("groupWithBobInIt::aliceUserName", aliceDistributionMessage); + + byte[] ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert".getBytes()); + byte[] plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice); + + assertTrue(new String(plaintextFromAlice).equals("smert ze smert")); + } + + public void testBasicRatchet() + throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException + { + InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); + InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore(); + + GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore); + GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore); + + GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt"); + GroupCipher bobGroupCipher = new GroupCipher(bobStore, "groupWithBobInIt::aliceUserName"); + + byte[] aliceSenderKey = KeyHelper.generateSenderKey(); + ECKeyPair aliceSenderSigningKey = KeyHelper.generateSenderSigningKey(); + int aliceSenderKeyId = KeyHelper.generateSenderKeyId(); + + SenderKeyDistributionMessage aliceDistributionMessage = + aliceSessionBuilder.process("groupWithBobInIt", aliceSenderKeyId, 0, + aliceSenderKey, aliceSenderSigningKey); + + bobSessionBuilder.process("groupWithBobInIt::aliceUserName", aliceDistributionMessage); + + byte[] ciphertextFromAlice = aliceGroupCipher.encrypt("smert ze smert".getBytes()); + byte[] ciphertextFromAlice2 = aliceGroupCipher.encrypt("smert ze smert2".getBytes()); + byte[] ciphertextFromAlice3 = aliceGroupCipher.encrypt("smert ze smert3".getBytes()); + + byte[] plaintextFromAlice = bobGroupCipher.decrypt(ciphertextFromAlice); + + try { + bobGroupCipher.decrypt(ciphertextFromAlice); + throw new AssertionError("Should have ratcheted forward!"); + } catch (DuplicateMessageException dme) { + // good + } + + byte[] plaintextFromAlice2 = bobGroupCipher.decrypt(ciphertextFromAlice2); + byte[] plaintextFromAlice3 = bobGroupCipher.decrypt(ciphertextFromAlice3); + + assertTrue(new String(plaintextFromAlice).equals("smert ze smert")); + assertTrue(new String(plaintextFromAlice2).equals("smert ze smert2")); + assertTrue(new String(plaintextFromAlice3).equals("smert ze smert3")); + } + + public void testOutOfOrder() + throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException + { + InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); + InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore(); + + GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore); + GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore); + + GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt"); + GroupCipher bobGroupCipher = new GroupCipher(bobStore, "groupWithBobInIt::aliceUserName"); + + byte[] aliceSenderKey = KeyHelper.generateSenderKey(); + ECKeyPair aliceSenderSigningKey = KeyHelper.generateSenderSigningKey(); + int aliceSenderKeyId = KeyHelper.generateSenderKeyId(); + + SenderKeyDistributionMessage aliceDistributionMessage = + aliceSessionBuilder.process("groupWithBobInIt", aliceSenderKeyId, 0, + aliceSenderKey, aliceSenderSigningKey); + + bobSessionBuilder.process("groupWithBobInIt::aliceUserName", aliceDistributionMessage); + + + ArrayList<byte[]> ciphertexts = new ArrayList<>(100); + + for (int i=0;i<100;i++) { + ciphertexts.add(aliceGroupCipher.encrypt("up the punks".getBytes())); + } + + while (ciphertexts.size() > 0) { + int index = randomInt() % ciphertexts.size(); + byte[] ciphertext = ciphertexts.remove(index); + byte[] plaintext = bobGroupCipher.decrypt(ciphertext); + + assertTrue(new String(plaintext).equals("up the punks")); + } + } + + public void testEncryptNoSession() { + InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); + GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt"); + try { + aliceGroupCipher.encrypt("up the punks".getBytes()); + throw new AssertionError("Should have failed!"); + } catch (NoSessionException nse) { + // good + } + } + + private int randomInt() { + try { + return SecureRandom.getInstance("SHA1PRNG").nextInt(Integer.MAX_VALUE); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } +} diff --git a/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java b/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java new file mode 100644 index 00000000..450d802d --- /dev/null +++ b/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java @@ -0,0 +1,33 @@ +package org.whispersystems.test.groups; + +import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord; +import org.whispersystems.libaxolotl.groups.state.SenderKeyStore; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class InMemorySenderKeyStore implements SenderKeyStore { + + private final Map<String, SenderKeyRecord> store = new HashMap<>(); + + @Override + public void storeSenderKey(String senderKeyId, SenderKeyRecord record) { + store.put(senderKeyId, record); + } + + @Override + public SenderKeyRecord loadSenderKey(String senderKeyId) { + try { + SenderKeyRecord record = store.get(senderKeyId); + + if (record == null) { + return new SenderKeyRecord(); + } else { + return new SenderKeyRecord(record.serialize()); + } + } catch (IOException e) { + throw new AssertionError(e); + } + } +} |