public void TestTooFarInFuture()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            SenderKeyName aliceName = GroupSender;

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, aliceName);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, aliceName);

            SenderKeyDistributionMessage aliceDistributionMessage = aliceSessionBuilder.Create(aliceName);

            bobSessionBuilder.Process(aliceName, aliceDistributionMessage);

            for (int i = 0; i < 2001; i++)
            {
                aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("up the punks"));
            }

            byte[] tooFarCiphertext = aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("notta gonna worka"));
            try
            {
                bobGroupCipher.Decrypt(tooFarCiphertext);
                throw new Exception("Should have failed!");
            }
            catch (InvalidMessageException)
            {
                // good
            }
        }
        public void TestNoSession()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, GroupSender);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, GroupSender);

            SenderKeyDistributionMessage sentAliceDistributionMessage     = aliceSessionBuilder.Create(GroupSender);
            SenderKeyDistributionMessage receivedAliceDistributionMessage = new SenderKeyDistributionMessage(sentAliceDistributionMessage.Serialize());

            //    bobSessionBuilder.process(GROUP_SENDER, receivedAliceDistributionMessage);

            byte[] ciphertextFromAlice = aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("smert ze smert"));
            try
            {
                byte[] plaintextFromAlice = bobGroupCipher.Decrypt(ciphertextFromAlice);
                throw new Exception("Should be no session!");
            }
            catch (NoSessionException)
            {
                // good
            }
        }
        public void TestOutOfOrder()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            SenderKeyName aliceName = GroupSender;

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, aliceName);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, aliceName);

            SenderKeyDistributionMessage aliceDistributionMessage =
                aliceSessionBuilder.Create(aliceName);

            bobSessionBuilder.Process(aliceName, aliceDistributionMessage);

            List <byte[]> ciphertexts = new List <byte[]>(100);

            for (int i = 0; i < 100; i++)
            {
                ciphertexts.Add(aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("up the punks")));
            }

            while (ciphertexts.Count > 0)
            {
                int    index      = (int)(RandomUInt() % ciphertexts.Count);
                byte[] ciphertext = ciphertexts[index];
                ciphertexts.RemoveAt(index);
                byte[] plaintext = bobGroupCipher.Decrypt(ciphertext);

                Assert.AreEqual("up the punks", Encoding.UTF8.GetString(plaintext));
            }
        }
        public void TestEncryptNoSession()
        {
            InMemorySenderKeyStore aliceStore       = new InMemorySenderKeyStore();
            GroupCipher            aliceGroupCipher = new GroupCipher(aliceStore, new SenderKeyName("coolio groupio", new SignalProtocolAddress("+10002223333", 1)));

            try
            {
                aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("up the punks"));
                throw new Exception("Should have failed!");
            }
            catch (NoSessionException)
            {
                // good
            }
        }
        public void TestBasicRatchet()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            SenderKeyName aliceName = GroupSender;

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, aliceName);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, aliceName);

            SenderKeyDistributionMessage sentAliceDistributionMessage =
                aliceSessionBuilder.Create(aliceName);
            SenderKeyDistributionMessage receivedAliceDistributionMessage =
                new SenderKeyDistributionMessage(sentAliceDistributionMessage.Serialize());

            bobSessionBuilder.Process(aliceName, receivedAliceDistributionMessage);

            byte[] ciphertextFromAlice  = aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("smert ze smert"));
            byte[] ciphertextFromAlice2 = aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("smert ze smert2"));
            byte[] ciphertextFromAlice3 = aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("smert ze smert3"));

            byte[] plaintextFromAlice = bobGroupCipher.Decrypt(ciphertextFromAlice);

            try
            {
                bobGroupCipher.Decrypt(ciphertextFromAlice);
                throw new Exception("Should have ratcheted forward!");
            }
            catch (DuplicateMessageException)
            {
                // good
            }

            byte[] plaintextFromAlice2 = bobGroupCipher.Decrypt(ciphertextFromAlice2);
            byte[] plaintextFromAlice3 = bobGroupCipher.Decrypt(ciphertextFromAlice3);

            Assert.AreEqual("smert ze smert", Encoding.UTF8.GetString(plaintextFromAlice));
            Assert.AreEqual("smert ze smert2", Encoding.UTF8.GetString(plaintextFromAlice2));
            Assert.AreEqual("smert ze smert3", Encoding.UTF8.GetString(plaintextFromAlice3));
        }
        public void TestBasicEncryptDecrypt()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, GroupSender);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, GroupSender);

            SenderKeyDistributionMessage sentAliceDistributionMessage     = aliceSessionBuilder.Create(GroupSender);
            SenderKeyDistributionMessage receivedAliceDistributionMessage = new SenderKeyDistributionMessage(sentAliceDistributionMessage.Serialize());

            bobSessionBuilder.Process(GroupSender, receivedAliceDistributionMessage);

            byte[] ciphertextFromAlice = aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("smert ze smert"));
            byte[] plaintextFromAlice  = bobGroupCipher.Decrypt(ciphertextFromAlice);

            Assert.AreEqual("smert ze smert", Encoding.UTF8.GetString(plaintextFromAlice));
        }
        public void TestMessageKeyLimit()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            SenderKeyName aliceName = GroupSender;

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, aliceName);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, aliceName);

            SenderKeyDistributionMessage aliceDistributionMessage = aliceSessionBuilder.Create(aliceName);

            bobSessionBuilder.Process(aliceName, aliceDistributionMessage);

            List <byte[]> inflight = new List <byte[]>();

            for (int i = 0; i < 2010; i++)
            {
                inflight.Add(aliceGroupCipher.Encrypt(Encoding.UTF8.GetBytes("up the punks")));
            }

            bobGroupCipher.Decrypt(inflight[1000]);
            bobGroupCipher.Decrypt(inflight[inflight.Count - 1]);

            try
            {
                bobGroupCipher.Decrypt(inflight[0]);
                throw new Exception("Should have failed!");
            }
            catch (DuplicateMessageException)
            {
                // good
            }
        }
        public void TestLargeMessages()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
            GroupSessionBuilder bobSessionBuilder   = new GroupSessionBuilder(bobStore);

            GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, GroupSender);
            GroupCipher bobGroupCipher   = new GroupCipher(bobStore, GroupSender);

            SenderKeyDistributionMessage sentAliceDistributionMessage     = aliceSessionBuilder.Create(GroupSender);
            SenderKeyDistributionMessage receivedAliceDistributionMessage = new SenderKeyDistributionMessage(sentAliceDistributionMessage.Serialize());

            bobSessionBuilder.Process(GroupSender, receivedAliceDistributionMessage);

            byte[] plaintext = new byte[1024 * 1024];
            new Random().NextBytes(plaintext);

            byte[] ciphertextFromAlice = aliceGroupCipher.Encrypt(plaintext);
            byte[] plaintextFromAlice  = bobGroupCipher.Decrypt(ciphertextFromAlice);

            CollectionAssert.AreEqual(plaintext, plaintextFromAlice);
        }
        public void TestLateJoin()
        {
            InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
            InMemorySenderKeyStore bobStore   = new InMemorySenderKeyStore();

            GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);


            SenderKeyName aliceName = GroupSender;

            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(Encoding.UTF8.GetBytes("up the punks up the punks up the punks"));
            }

            // 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(Encoding.UTF8.GetBytes("welcome to the group"));
            byte[] plaintext  = bobGroupCipher.Decrypt(ciphertext);

            Assert.AreEqual("welcome to the group", Encoding.UTF8.GetString(plaintext));
        }