public void TestBadMessageBundle() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); ISignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); EcKeyPair bobPreKeyPair = Curve.GenerateKeyPair(); EcKeyPair bobSignedPreKeyPair = Curve.GenerateKeyPair(); byte[] bobSignedPreKeySignature = Curve.CalculateSignature(bobStore.GetIdentityKeyPair().GetPrivateKey(), bobSignedPreKeyPair.GetPublicKey().Serialize()); PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.GetPublicKey(), 22, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().GetPublicKey()); bobStore.StorePreKey(31337, new PreKeyRecord(bobPreKey.GetPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(22, new SignedPreKeyRecord(22, DateUtil.CurrentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); aliceSessionBuilder.Process(bobPreKey); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); CiphertextMessage outgoingMessageOne = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PrekeyType, outgoingMessageOne.GetMessageType()); byte[] goodMessage = outgoingMessageOne.Serialize(); byte[] badMessage = new byte[goodMessage.Length]; Array.Copy(goodMessage, 0, badMessage, 0, badMessage.Length); badMessage[badMessage.Length - 10] ^= 0x01; PreKeySignalMessage incomingMessage = new PreKeySignalMessage(badMessage); SessionCipher bobSessionCipher = new SessionCipher(bobStore, AliceAddress); byte[] plaintext = new byte[0]; try { plaintext = bobSessionCipher.Decrypt(incomingMessage); throw new Exception("Decrypt should have failed!"); } catch (InvalidMessageException) { // good. } Assert.IsTrue(bobStore.ContainsPreKey(31337)); plaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(goodMessage)); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); Assert.IsFalse(bobStore.ContainsPreKey(31337)); }
public void TestRepeatBundleMessageV3() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); ISignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); EcKeyPair bobPreKeyPair = Curve.GenerateKeyPair(); EcKeyPair bobSignedPreKeyPair = Curve.GenerateKeyPair(); byte[] bobSignedPreKeySignature = Curve.CalculateSignature(bobStore.GetIdentityKeyPair().GetPrivateKey(), bobSignedPreKeyPair.GetPublicKey().Serialize()); PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.GetPublicKey(), 22, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().GetPublicKey()); bobStore.StorePreKey(31337, new PreKeyRecord(bobPreKey.GetPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(22, new SignedPreKeyRecord(22, DateUtil.CurrentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); aliceSessionBuilder.Process(bobPreKey); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); CiphertextMessage outgoingMessageOne = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); CiphertextMessage outgoingMessageTwo = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PrekeyType, outgoingMessageOne.GetMessageType()); Assert.AreEqual(CiphertextMessage.PrekeyType, outgoingMessageTwo.GetMessageType()); PreKeySignalMessage incomingMessage = new PreKeySignalMessage(outgoingMessageOne.Serialize()); SessionCipher bobSessionCipher = new SessionCipher(bobStore, AliceAddress); byte[] plaintext = bobSessionCipher.Decrypt(incomingMessage); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobOutgoingMessage = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); byte[] alicePlaintext = aliceSessionCipher.Decrypt(new SignalMessage(bobOutgoingMessage.Serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(alicePlaintext)); // The test PreKeySignalMessage incomingMessageTwo = new PreKeySignalMessage(outgoingMessageTwo.Serialize()); plaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(incomingMessageTwo.Serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); bobOutgoingMessage = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); alicePlaintext = aliceSessionCipher.Decrypt(new SignalMessage(bobOutgoingMessage.Serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(alicePlaintext)); }
public void TestBasicSimultaneousInitiate() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); ISignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); PreKeyBundle alicePreKeyBundle = CreateAlicePreKeyBundle(aliceStore); PreKeyBundle bobPreKeyBundle = CreateBobPreKeyBundle(bobStore); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, AliceAddress); SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); SessionCipher bobSessionCipher = new SessionCipher(bobStore, AliceAddress); aliceSessionBuilder.Process(bobPreKeyBundle); bobSessionBuilder.Process(alicePreKeyBundle); CiphertextMessage messageForBob = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes("hey there")); CiphertextMessage messageForAlice = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes("sample message")); Assert.AreEqual(CiphertextMessage.PrekeyType, messageForBob.GetMessageType()); Assert.AreEqual(CiphertextMessage.PrekeyType, messageForAlice.GetMessageType()); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); byte[] alicePlaintext = aliceSessionCipher.Decrypt(new PreKeySignalMessage(messageForAlice.Serialize())); byte[] bobPlaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(messageForBob.Serialize())); Assert.AreEqual("sample message", Encoding.UTF8.GetString(alicePlaintext)); Assert.AreEqual("hey there", Encoding.UTF8.GetString(bobPlaintext)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BobAddress).GetSessionState().GetSessionVersion()); Assert.AreEqual((uint)3, bobStore.LoadSession(AliceAddress).GetSessionState().GetSessionVersion()); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); CiphertextMessage aliceResponse = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes("second message")); Assert.AreEqual(CiphertextMessage.WhisperType, aliceResponse.GetMessageType()); byte[] responsePlaintext = bobSessionCipher.Decrypt(new SignalMessage(aliceResponse.Serialize())); Assert.AreEqual("second message", Encoding.UTF8.GetString(responsePlaintext)); Assert.IsTrue(IsSessionIdEqual(aliceStore, bobStore)); CiphertextMessage finalMessage = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes("third message")); Assert.AreEqual(CiphertextMessage.WhisperType, finalMessage.GetMessageType()); byte[] finalPlaintext = aliceSessionCipher.Decrypt(new SignalMessage(finalMessage.Serialize())); Assert.AreEqual("third message", Encoding.UTF8.GetString(finalPlaintext)); Assert.IsTrue(IsSessionIdEqual(aliceStore, bobStore)); }
public void TestOptionalOneTimePreKey() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); ISignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); EcKeyPair bobPreKeyPair = Curve.GenerateKeyPair(); EcKeyPair bobSignedPreKeyPair = Curve.GenerateKeyPair(); byte[] bobSignedPreKeySignature = Curve.CalculateSignature(bobStore.GetIdentityKeyPair().GetPrivateKey(), bobSignedPreKeyPair.GetPublicKey().Serialize()); PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 0, null, 22, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().GetPublicKey()); aliceSessionBuilder.Process(bobPreKey); Assert.IsTrue(aliceStore.ContainsSession(BobAddress)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BobAddress).GetSessionState().GetSessionVersion()); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); CiphertextMessage outgoingMessage = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(outgoingMessage.GetMessageType(), CiphertextMessage.PrekeyType); PreKeySignalMessage incomingMessage = new PreKeySignalMessage(outgoingMessage.Serialize()); Assert.IsFalse(incomingMessage.GetPreKeyId().HasValue); bobStore.StorePreKey(31337, new PreKeyRecord(bobPreKey.GetPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(22, new SignedPreKeyRecord(22, DateUtil.CurrentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); SessionCipher bobSessionCipher = new SessionCipher(bobStore, AliceAddress); byte[] plaintext = bobSessionCipher.Decrypt(incomingMessage); Assert.IsTrue(bobStore.ContainsSession(AliceAddress)); Assert.AreEqual((uint)3, bobStore.LoadSession(AliceAddress).GetSessionState().GetSessionVersion()); Assert.IsNotNull(bobStore.LoadSession(AliceAddress).GetSessionState().GetAliceBaseKey()); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); }
public void TestBadSignedPreKeySignature() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); IDentityKeyStore bobIdentityKeyStore = new TestInMemoryIdentityKeyStore(); EcKeyPair bobPreKeyPair = Curve.GenerateKeyPair(); EcKeyPair bobSignedPreKeyPair = Curve.GenerateKeyPair(); byte[] bobSignedPreKeySignature = Curve.CalculateSignature(bobIdentityKeyStore.GetIdentityKeyPair().GetPrivateKey(), bobSignedPreKeyPair.GetPublicKey().Serialize()); for (int i = 0; i < bobSignedPreKeySignature.Length * 8; i++) { byte[] modifiedSignature = new byte[bobSignedPreKeySignature.Length]; Array.Copy(bobSignedPreKeySignature, 0, modifiedSignature, 0, modifiedSignature.Length); modifiedSignature[i / 8] ^= (byte)(0x01 << (i % 8)); PreKeyBundle bobPreKey = new PreKeyBundle(bobIdentityKeyStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.GetPublicKey(), 22, bobSignedPreKeyPair.GetPublicKey(), modifiedSignature, bobIdentityKeyStore.GetIdentityKeyPair().GetPublicKey()); try { aliceSessionBuilder.Process(bobPreKey); throw new Exception("Accepted modified device key signature!"); } catch (InvalidKeyException) { // good } } PreKeyBundle bobPreKey2 = new PreKeyBundle(bobIdentityKeyStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.GetPublicKey(), 22, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, bobIdentityKeyStore.GetIdentityKeyPair().GetPublicKey()); aliceSessionBuilder.Process(bobPreKey2); }
public void TestMessageKeyLimits() { SessionRecord aliceSessionRecord = new SessionRecord(); SessionRecord bobSessionRecord = new SessionRecord(); InitializeSessionsV3(aliceSessionRecord.GetSessionState(), bobSessionRecord.GetSessionState()); ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); ISignalProtocolStore 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.UTF8.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) { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); ISignalProtocolStore 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.UTF8.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.UTF8.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.UTF8.GetBytes("смерть за смерть " + i)); aliceCiphertextMessages.Add(aliceCipher.Encrypt(Encoding.UTF8.GetBytes("смерть за смерть " + i))); } ulong seed = DateUtil.CurrentTimeMillis(); HelperMethods.Shuffle(aliceCiphertextMessages, new Random((int)seed)); HelperMethods.Shuffle(alicePlaintextMessages, new Random((int)seed)); for (int i = 0; i < aliceCiphertextMessages.Count / 2; i++) { byte[] receivedPlaintext = bobCipher.Decrypt(new SignalMessage(aliceCiphertextMessages[i].Serialize())); Assert.IsTrue(ByteUtil.IsEqual(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.UTF8.GetBytes("смерть за смерть " + i)); bobCiphertextMessages.Add(bobCipher.Encrypt(Encoding.UTF8.GetBytes("смерть за смерть " + i))); } seed = DateUtil.CurrentTimeMillis(); HelperMethods.Shuffle(bobCiphertextMessages, new Random((int)seed)); HelperMethods.Shuffle(bobPlaintextMessages, new Random((int)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]); } }
public void TestBasicPreKeyV3() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); ISignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); EcKeyPair bobPreKeyPair = Curve.GenerateKeyPair(); EcKeyPair bobSignedPreKeyPair = Curve.GenerateKeyPair(); byte[] bobSignedPreKeySignature = Curve.CalculateSignature(bobStore.GetIdentityKeyPair().GetPrivateKey(), bobSignedPreKeyPair.GetPublicKey().Serialize()); PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.GetPublicKey(), 22, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().GetPublicKey()); aliceSessionBuilder.Process(bobPreKey); Assert.IsTrue(aliceStore.ContainsSession(BobAddress)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BobAddress).GetSessionState().GetSessionVersion()); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); CiphertextMessage outgoingMessage = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PrekeyType, outgoingMessage.GetMessageType()); PreKeySignalMessage incomingMessage = new PreKeySignalMessage(outgoingMessage.Serialize()); bobStore.StorePreKey(31337, new PreKeyRecord(bobPreKey.GetPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(22, new SignedPreKeyRecord(22, DateUtil.CurrentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); SessionCipher bobSessionCipher = new SessionCipher(bobStore, AliceAddress); byte[] plaintext = bobSessionCipher.Decrypt(incomingMessage, new BobDecryptionCallback(bobStore, originalMessage)); Assert.IsTrue(bobStore.ContainsSession(AliceAddress)); Assert.AreEqual((uint)3, bobStore.LoadSession(AliceAddress).GetSessionState().GetSessionVersion()); Assert.IsNotNull(bobStore.LoadSession(AliceAddress).GetSessionState().GetAliceBaseKey()); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobOutgoingMessage = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WhisperType, bobOutgoingMessage.GetMessageType()); byte[] alicePlaintext = aliceSessionCipher.Decrypt(new SignalMessage(bobOutgoingMessage.Serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(alicePlaintext)); RunInteraction(aliceStore, bobStore); aliceStore = new TestInMemorySignalProtocolStore(); aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); bobPreKeyPair = Curve.GenerateKeyPair(); bobSignedPreKeyPair = Curve.GenerateKeyPair(); bobSignedPreKeySignature = Curve.CalculateSignature(bobStore.GetIdentityKeyPair().GetPrivateKey(), bobSignedPreKeyPair.GetPublicKey().Serialize()); bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31338, bobPreKeyPair.GetPublicKey(), 23, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, bobStore.GetIdentityKeyPair().GetPublicKey()); bobStore.StorePreKey(31338, new PreKeyRecord(bobPreKey.GetPreKeyId(), bobPreKeyPair)); bobStore.StoreSignedPreKey(23, new SignedPreKeyRecord(23, DateUtil.CurrentTimeMillis(), bobSignedPreKeyPair, bobSignedPreKeySignature)); aliceSessionBuilder.Process(bobPreKey); outgoingMessage = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes(originalMessage)); try { plaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(outgoingMessage.Serialize())); throw new Exception("shouldn't be trusted!"); } catch (UntrustedIdentityException) { bobStore.SaveIdentity(AliceAddress, new PreKeySignalMessage(outgoingMessage.Serialize()).GetIdentityKey()); } plaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(outgoingMessage.Serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, Curve.GenerateKeyPair().GetPublicKey(), 23, bobSignedPreKeyPair.GetPublicKey(), bobSignedPreKeySignature, aliceStore.GetIdentityKeyPair().GetPublicKey()); try { aliceSessionBuilder.Process(bobPreKey); throw new Exception("shoulnd't be trusted!"); } catch (UntrustedIdentityException) { // good } }
public void TestRepeatedSimultaneousInitiateLostMessageRepeatedMessages() { ISignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); ISignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BobAddress); SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, AliceAddress); SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BobAddress); SessionCipher bobSessionCipher = new SessionCipher(bobStore, AliceAddress); // PreKeyBundle aliceLostPreKeyBundle = createAlicePreKeyBundle(aliceStore); PreKeyBundle bobLostPreKeyBundle = CreateBobPreKeyBundle(bobStore); aliceSessionBuilder.Process(bobLostPreKeyBundle); // bobSessionBuilder.process(aliceLostPreKeyBundle); CiphertextMessage lostMessageForBob = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes("hey there")); // CiphertextMessage lostMessageForAlice = bobSessionCipher.encrypt("sample message".getBytes()); for (int i = 0; i < 15; i++) { PreKeyBundle alicePreKeyBundle = CreateAlicePreKeyBundle(aliceStore); PreKeyBundle bobPreKeyBundle = CreateBobPreKeyBundle(bobStore); aliceSessionBuilder.Process(bobPreKeyBundle); bobSessionBuilder.Process(alicePreKeyBundle); CiphertextMessage messageForBob = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes("hey there")); CiphertextMessage messageForAlice = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes("sample message")); Assert.AreEqual <uint>(messageForBob.GetMessageType(), CiphertextMessage.PrekeyType); Assert.AreEqual <uint>(messageForAlice.GetMessageType(), CiphertextMessage.PrekeyType); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); byte[] alicePlaintext = aliceSessionCipher.Decrypt(new PreKeySignalMessage(messageForAlice.Serialize())); byte[] bobPlaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(messageForBob.Serialize())); Assert.IsTrue(Encoding.UTF8.GetString(alicePlaintext).Equals("sample message")); Assert.IsTrue(Encoding.UTF8.GetString(bobPlaintext).Equals("hey there")); Assert.IsTrue(aliceStore.LoadSession(BobAddress).GetSessionState().GetSessionVersion() == 3); Assert.IsTrue(bobStore.LoadSession(AliceAddress).GetSessionState().GetSessionVersion() == 3); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); } for (int i = 0; i < 50; i++) { CiphertextMessage messageForBobRepeat = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes("hey there")); CiphertextMessage messageForAliceRepeat = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes("sample message")); Assert.AreEqual <uint>(messageForBobRepeat.GetMessageType(), CiphertextMessage.WhisperType); Assert.AreEqual <uint>(messageForAliceRepeat.GetMessageType(), CiphertextMessage.WhisperType); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); byte[] alicePlaintextRepeat = aliceSessionCipher.Decrypt(new SignalMessage(messageForAliceRepeat.Serialize())); byte[] bobPlaintextRepeat = bobSessionCipher.Decrypt(new SignalMessage(messageForBobRepeat.Serialize())); Assert.IsTrue(Encoding.UTF8.GetString(alicePlaintextRepeat).Equals("sample message")); Assert.IsTrue(Encoding.UTF8.GetString(bobPlaintextRepeat).Equals("hey there")); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); } CiphertextMessage aliceResponse = aliceSessionCipher.Encrypt(Encoding.UTF8.GetBytes("second message")); Assert.AreEqual <uint>(aliceResponse.GetMessageType(), CiphertextMessage.WhisperType); byte[] responsePlaintext = bobSessionCipher.Decrypt(new SignalMessage(aliceResponse.Serialize())); Assert.IsTrue(Encoding.UTF8.GetString(responsePlaintext).Equals("second message")); Assert.IsTrue(IsSessionIdEqual(aliceStore, bobStore)); CiphertextMessage finalMessage = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes("third message")); Assert.AreEqual <uint>(finalMessage.GetMessageType(), CiphertextMessage.WhisperType); byte[] finalPlaintext = aliceSessionCipher.Decrypt(new SignalMessage(finalMessage.Serialize())); Assert.IsTrue(Encoding.UTF8.GetString(finalPlaintext).Equals("third message")); Assert.IsTrue(IsSessionIdEqual(aliceStore, bobStore)); byte[] lostMessagePlaintext = bobSessionCipher.Decrypt(new PreKeySignalMessage(lostMessageForBob.Serialize())); Assert.IsTrue(Encoding.UTF8.GetString(lostMessagePlaintext).Equals("hey there")); Assert.IsFalse(IsSessionIdEqual(aliceStore, bobStore)); CiphertextMessage blastFromThePast = bobSessionCipher.Encrypt(Encoding.UTF8.GetBytes("unexpected!")); byte[] blastFromThePastPlaintext = aliceSessionCipher.Decrypt(new SignalMessage(blastFromThePast.Serialize())); Assert.IsTrue(Encoding.UTF8.GetString(blastFromThePastPlaintext).Equals("unexpected!")); Assert.IsTrue(IsSessionIdEqual(aliceStore, bobStore)); }