public void TestEncryptFromWrongIdentity()
        {
            TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
            TestInMemorySignalProtocolStore bobStore   = new TestInMemorySignalProtocolStore();

            InitializeSessions(aliceStore, bobStore);

            ECKeyPair           trustRoot         = Curve.generateKeyPair();
            ECKeyPair           randomKeyPair     = Curve.generateKeyPair();
            SenderCertificate   senderCertificate = CreateCertificateFor(trustRoot, "+14151111111", 1, randomKeyPair.getPublicKey(), 31337);
            SealedSessionCipher aliceCipher       = new SealedSessionCipher(aliceStore, new SignalProtocolAddress("+14151111111", 1));

            byte[] ciphertext = aliceCipher.Encrypt(new SignalProtocolAddress("+14152222222", 1),
                                                    senderCertificate, Encoding.ASCII.GetBytes("smert za smert"));


            SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, new SignalProtocolAddress("+14152222222", 1));

            try
            {
                bobCipher.Decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
            }
            catch (InvalidMetadataMessageException)
            {
                // good
            }
        }
        private void InitializeSessions(TestInMemorySignalProtocolStore aliceStore, TestInMemorySignalProtocolStore bobStore)
        {
            ECKeyPair          bobPreKey       = Curve.generateKeyPair();
            IdentityKeyPair    bobIdentityKey  = bobStore.GetIdentityKeyPair();
            SignedPreKeyRecord bobSignedPreKey = KeyHelper.generateSignedPreKey(bobIdentityKey, 2);

            PreKeyBundle   bobBundle           = new PreKeyBundle(1, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey());
            SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, new SignalProtocolAddress("+14152222222", 1));

            aliceSessionBuilder.process(bobBundle);

            bobStore.StoreSignedPreKey(2, bobSignedPreKey);
            bobStore.StorePreKey(1, new PreKeyRecord(1, bobPreKey));
        }
        public void TestEncryptDecrypt()
        {
            TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
            TestInMemorySignalProtocolStore bobStore   = new TestInMemorySignalProtocolStore();

            InitializeSessions(aliceStore, bobStore);

            ECKeyPair           trustRoot         = Curve.generateKeyPair();
            SenderCertificate   senderCertificate = CreateCertificateFor(trustRoot, "+14151111111", 1, aliceStore.GetIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
            SealedSessionCipher aliceCipher       = new SealedSessionCipher(aliceStore, new SignalProtocolAddress("+14151111111", 1));

            byte[] ciphertext = aliceCipher.Encrypt(new SignalProtocolAddress("+14152222222", 1),
                                                    senderCertificate, Encoding.ASCII.GetBytes("smert za smert"));


            SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, new SignalProtocolAddress("+14152222222", 1));

            (SignalProtocolAddress, byte[])plaintext = bobCipher.Decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);

            CollectionAssert.AreEqual(plaintext.Item2, Encoding.ASCII.GetBytes("smert za smert"));
            Assert.AreEqual(plaintext.Item1.Name, "+14151111111");
            Assert.AreEqual(plaintext.Item1.DeviceId, (uint)1);
        }
        public void TestMessageKeyLimits()
        {
            SessionRecord aliceSessionRecord = new SessionRecord();
            SessionRecord bobSessionRecord   = new SessionRecord();

            InitializeSessionsV3(aliceSessionRecord.getSessionState(), bobSessionRecord.getSessionState());

            SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
            SignalProtocolStore bobStore   = new TestInMemorySignalProtocolStore();

            aliceStore.StoreSession(new SignalProtocolAddress("+14159999999", 1), aliceSessionRecord);
            bobStore.StoreSession(new SignalProtocolAddress("+14158888888", 1), bobSessionRecord);

            SessionCipher aliceCipher = new SessionCipher(aliceStore, new SignalProtocolAddress("+14159999999", 1));
            SessionCipher bobCipher   = new SessionCipher(bobStore, new SignalProtocolAddress("+14158888888", 1));

            List <CiphertextMessage> inflight = new List <CiphertextMessage>();

            for (int i = 0; i < 2010; i++)
            {
                inflight.Add(aliceCipher.encrypt(Encoding.ASCII.GetBytes("you've never been so hungry, you've never been so cold")));
            }

            bobCipher.decrypt(new SignalMessage(inflight[1000].serialize()));
            bobCipher.decrypt(new SignalMessage(inflight[inflight.Count - 1].serialize()));

            try
            {
                bobCipher.decrypt(new SignalMessage(inflight[0].serialize()));
                throw new Exception("Should have failed!");
            }
            catch (DuplicateMessageException)
            {
                // good
            }
        }
        private void RunInteraction(SessionRecord aliceSessionRecord, SessionRecord bobSessionRecord)
        {
            SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
            SignalProtocolStore bobStore   = new TestInMemorySignalProtocolStore();

            aliceStore.StoreSession(new SignalProtocolAddress("+14159999999", 1), aliceSessionRecord);
            bobStore.StoreSession(new SignalProtocolAddress("+14158888888", 1), bobSessionRecord);

            SessionCipher aliceCipher = new SessionCipher(aliceStore, new SignalProtocolAddress("+14159999999", 1));
            SessionCipher bobCipher   = new SessionCipher(bobStore, new SignalProtocolAddress("+14158888888", 1));

            byte[]            alicePlaintext = Encoding.ASCII.GetBytes("This is a plaintext message.");
            CiphertextMessage message        = aliceCipher.encrypt(alicePlaintext);

            byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));

            CollectionAssert.AreEqual(alicePlaintext, bobPlaintext);

            byte[]            bobReply = Encoding.ASCII.GetBytes("This is a message from Bob.");
            CiphertextMessage reply    = bobCipher.encrypt(bobReply);

            byte[] receivedReply = aliceCipher.decrypt(new SignalMessage(reply.serialize()));

            CollectionAssert.AreEqual(bobReply, receivedReply);

            List <CiphertextMessage> aliceCiphertextMessages = new List <CiphertextMessage>();
            List <byte[]>            alicePlaintextMessages  = new List <byte[]>();

            for (int i = 0; i < 50; i++)
            {
                alicePlaintextMessages.Add(Encoding.ASCII.GetBytes("смерть за смерть " + i));
                aliceCiphertextMessages.Add(aliceCipher.encrypt(Encoding.ASCII.GetBytes("смерть за смерть " + i)));
            }

            int seed = (int)DateTime.Now.Ticks;

            Shuffle(aliceCiphertextMessages, new Random(seed));
            Shuffle(alicePlaintextMessages, new Random(seed));

            for (int i = 0; i < aliceCiphertextMessages.Count / 2; i++)
            {
                byte[] receivedPlaintext = bobCipher.decrypt(new SignalMessage(aliceCiphertextMessages[i].serialize()));
                CollectionAssert.AreEqual(receivedPlaintext, alicePlaintextMessages[i]);
            }

            List <CiphertextMessage> bobCiphertextMessages = new List <CiphertextMessage>();
            List <byte[]>            bobPlaintextMessages  = new List <byte[]>();

            for (int i = 0; i < 20; i++)
            {
                bobPlaintextMessages.Add(Encoding.ASCII.GetBytes("смерть за смерть " + i));
                bobCiphertextMessages.Add(bobCipher.encrypt(Encoding.ASCII.GetBytes("смерть за смерть " + i)));
            }

            seed = (int)DateTime.Now.Ticks;

            Shuffle(bobCiphertextMessages, new Random(seed));
            Shuffle(bobPlaintextMessages, new Random(seed));

            for (int i = 0; i < bobCiphertextMessages.Count / 2; i++)
            {
                byte[] receivedPlaintext = aliceCipher.decrypt(new SignalMessage(bobCiphertextMessages[i].serialize()));
                CollectionAssert.AreEqual(receivedPlaintext, bobPlaintextMessages[i]);
            }

            for (int i = aliceCiphertextMessages.Count / 2; i < aliceCiphertextMessages.Count; i++)
            {
                byte[] receivedPlaintext = bobCipher.decrypt(new SignalMessage(aliceCiphertextMessages[i].serialize()));
                CollectionAssert.AreEqual(receivedPlaintext, alicePlaintextMessages[i]);
            }

            for (int i = bobCiphertextMessages.Count / 2; i < bobCiphertextMessages.Count; i++)
            {
                byte[] receivedPlaintext = aliceCipher.decrypt(new SignalMessage(bobCiphertextMessages[i].serialize()));
                CollectionAssert.AreEqual(receivedPlaintext, bobPlaintextMessages[i]);
            }
        }