public void testRepeatBundleMessageV3() { SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SignalProtocolStore 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, BOB_ADDRESS); CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); CiphertextMessage outgoingMessageTwo = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, outgoingMessageOne.getType()); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, outgoingMessageTwo.getType()); PreKeySignalMessage incomingMessage = new PreKeySignalMessage(outgoingMessageOne.serialize()); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); 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 OutgoingPushMessage encrypt(SignalProtocolAddress destination, byte[] unpaddedMessage, bool legacy, bool silent) { SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, destination); PushTransportDetails transportDetails = new PushTransportDetails(sessionCipher.getSessionVersion()); CiphertextMessage message = sessionCipher.encrypt(transportDetails.getPaddedMessageBody(unpaddedMessage)); uint remoteRegistrationId = sessionCipher.getRemoteRegistrationId(); String body = Base64.encodeBytes(message.serialize()); uint type; switch (message.getType()) { case CiphertextMessage.PREKEY_TYPE: type = (uint)Envelope.Types.Type.PrekeyBundle; break; // todo check case CiphertextMessage.WHISPER_TYPE: type = (uint)Envelope.Types.Type.Ciphertext; break; // todo check default: throw new Exception("Bad type: " + message.getType()); } return(new OutgoingPushMessage(type, destination.DeviceId, remoteRegistrationId, legacy ? body : null, legacy ? null : body, silent)); }
public OutgoingPushMessage Encrypt(SignalProtocolAddress destination, UnidentifiedAccess?unidentifiedAccess, byte[] unpaddedMessage) { if (unidentifiedAccess != null) { SealedSessionCipher sessionCipher = new SealedSessionCipher(signalProtocolStore, localAddress.Uuid, localAddress.GetNumber(), 1); PushTransportDetails transportDetails = new PushTransportDetails((uint)sessionCipher.GetSessionVersion(destination)); byte[] ciphertext = sessionCipher.Encrypt(destination, unidentifiedAccess.UnidentifiedCertificate, transportDetails.getPaddedMessageBody(unpaddedMessage)); string body = Base64.EncodeBytes(ciphertext); uint remoteRegistrationId = (uint)sessionCipher.GetRemoteRegistrationId(destination); return(new OutgoingPushMessage((uint)Envelope.Types.Type.UnidentifiedSender, destination.DeviceId, remoteRegistrationId, body)); } else { SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, destination); PushTransportDetails transportDetails = new PushTransportDetails(sessionCipher.getSessionVersion()); CiphertextMessage message = sessionCipher.encrypt(transportDetails.getPaddedMessageBody(unpaddedMessage)); uint remoteRegistrationId = sessionCipher.getRemoteRegistrationId(); string body = Base64.EncodeBytes(message.serialize()); var type = (message.getType()) switch { CiphertextMessage.PREKEY_TYPE => (uint)Envelope.Types.Type.PrekeyBundle, CiphertextMessage.WHISPER_TYPE => (uint)Envelope.Types.Type.Ciphertext, _ => throw new Exception("Bad type: " + message.getType()), }; return(new OutgoingPushMessage(type, destination.DeviceId, remoteRegistrationId, body)); } }
public void testBadMessageBundle() { SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SignalProtocolStore 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, BOB_ADDRESS); CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, outgoingMessageOne.getType()); 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, ALICE_ADDRESS); 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 testSimultaneousInitiateLostMessage() { AxolotlStore aliceStore = new TestInMemoryAxolotlStore(); AxolotlStore bobStore = new TestInMemoryAxolotlStore(); PreKeyBundle alicePreKeyBundle = createAlicePreKeyBundle(aliceStore); PreKeyBundle bobPreKeyBundle = createBobPreKeyBundle(bobStore); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS); SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); 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.PREKEY_TYPE, messageForBob.getType()); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, messageForAlice.getType()); Assert.IsFalse(isSessionIdEqual(aliceStore, bobStore)); byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeyWhisperMessage(messageForAlice.serialize())); byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(messageForBob.serialize())); Assert.AreEqual("sample message", Encoding.UTF8.GetString(alicePlaintext)); Assert.AreEqual("hey there", Encoding.UTF8.GetString(bobPlaintext)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion()); Assert.AreEqual((uint)3, bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getSessionVersion()); Assert.IsFalse(isSessionIdEqual(aliceStore, bobStore)); CiphertextMessage aliceResponse = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes("second message")); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, aliceResponse.getType()); // byte[] responsePlaintext = bobSessionCipher.decrypt(new WhisperMessage(aliceResponse.serialize())); // // assertTrue(new String(responsePlaintext).equals("second message")); // assertTrue(isSessionIdEqual(aliceStore, bobStore)); Assert.IsFalse(isSessionIdEqual(aliceStore, bobStore)); CiphertextMessage finalMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes("third message")); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, finalMessage.getType()); byte[] finalPlaintext = aliceSessionCipher.decrypt(new WhisperMessage(finalMessage.serialize())); Assert.AreEqual("third message", Encoding.UTF8.GetString(finalPlaintext)); Assert.IsTrue(isSessionIdEqual(aliceStore, bobStore)); }
public void testOptionalOneTimePreKey() { SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SignalProtocolStore 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(BOB_ADDRESS)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion()); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(outgoingMessage.getType(), CiphertextMessage.PREKEY_TYPE); 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, ALICE_ADDRESS); byte[] plaintext = bobSessionCipher.decrypt(incomingMessage); Assert.IsTrue(bobStore.ContainsSession(ALICE_ADDRESS)); Assert.AreEqual((uint)3, bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getSessionVersion()); Assert.IsNotNull(bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getAliceBaseKey()); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); }
protected override void OnCreate(Bundle bundle) { // Getting saved data ISharedPreferences sharedPref = PreferenceManager.GetDefaultSharedPreferences(this); User SelectedFriend = JsonConvert.DeserializeObject <User>(sharedPref.GetString("SelectedFriend", string.Empty)); List <Models.Message> SelectedFriendMessageList = new List <Models.Message>(); SelectedFriendMessageList = JsonConvert.DeserializeObject <List <Models.Message> >(sharedPref.GetString("SelectedFriendMessageList", string.Empty)); foreach (Models.Message m in SelectedFriendMessageList) { SelectedFriend.SelectedUserMessages.Add(m); } InMemorySessionStore sessionStore = JsonConvert.DeserializeObject <InMemorySessionStore>(sharedPref.GetString("SessionStore", string.Empty)); var allSessions = JsonConvert.DeserializeObject <List <Session> >(sharedPref.GetString("AllSessions", string.Empty)); foreach (Session item in allSessions) { sessionStore.StoreSession(item.Name, item.DeviceID, item.array); } PreKeyStore preKeyStore = JsonConvert.DeserializeObject <InMemoryPreKeyStore>(sharedPref.GetString("PreKeyStore", string.Empty)); SignedPreKeyStore signedPreKeyStore = JsonConvert.DeserializeObject <InMemorySignedPreKeyStore>(sharedPref.GetString("SignedPreKeyStore", string.Empty)); InMemoryIdentityKeyStore identityStore = JsonConvert.DeserializeObject <InMemoryIdentityKeyStore>(sharedPref.GetString("IdentityStore", string.Empty)); IdentityKeyPair KeyPair = new IdentityKeyPair(JsonConvert.DeserializeObject <byte[]>(sharedPref.GetString("IdentityKeyPair", string.Empty))); uint RegistrationID = Convert.ToUInt32(sharedPref.GetString("RegistrationId", string.Empty)); identityStore.PutValues(KeyPair, RegistrationID); var allTrustedKeys = JsonConvert.DeserializeObject <List <TrustedKey> >(sharedPref.GetString("AllTrustedKeys", string.Empty)); foreach (TrustedKey item in allTrustedKeys) { identityStore.SaveIdentity(item.Name, new IdentityKey(item.Identity, 0)); } SignalProtocolAddress SelectedFriendAddress = new SignalProtocolAddress(SelectedFriend.RegisterationID.ToString(), 1); // Get the messages from the server base.OnCreate(bundle); TheirMessages = GetMessages(sharedPref, SelectedFriend, sessionStore, preKeyStore, signedPreKeyStore, identityStore, SelectedFriendAddress); // Set our view from the "ChatList" layout resource Title = SelectedFriend.Username; SetContentView(Resource.Layout.Message); listView = FindViewById <ListView>(Resource.Id.messageList); //***display FriendsListItem in ListView using Adapter listView.Adapter = adapter = new Adapter(this, TheirMessages, UserID); messageText = FindViewById <EditText>(Resource.Id.messageText); sendButton = FindViewById <Button>(Resource.Id.sendButton); // **implement messages sending and receiving here //listView.Adapter = adapter = new Adapter(this); sendButton.Click += (sender, e) => { SessionCipher sessionCipher = new SessionCipher(sessionStore, preKeyStore, signedPreKeyStore, identityStore, SelectedFriendAddress); CiphertextMessage cipherMessage = sessionCipher.encrypt(Encoding.UTF8.GetBytes(messageText.Text)); SelectedFriend.SelectedUserMessages.Add(new Models.Message() { MessageID = 1, MessageReceiverRegisID = SelectedFriend.RegisterationID, MessageSenderRegisID = RegistrationID, MessageText = messageText.Text, MessageTimestamp = DateTime.Now }); // Save stores in local Database ISharedPreferences sharedprefs = PreferenceManager.GetDefaultSharedPreferences(this); ISharedPreferencesEditor editor = sharedprefs.Edit(); SelectedFriendMessageList.Clear(); foreach (Models.Message m in SelectedFriend.SelectedUserMessages) { SelectedFriendMessageList.Add(m); } editor.PutString("SelectedFriendMessageList", JsonConvert.SerializeObject(SelectedFriendMessageList)); editor.PutString("SelectedFriend", JsonConvert.SerializeObject(SelectedFriend)); editor.PutString("PreKeyStore", JsonConvert.SerializeObject(preKeyStore)); editor.PutString("SignedPreKeyStore", JsonConvert.SerializeObject(signedPreKeyStore)); List <Session> AllSessions = sessionStore.GetAllSessions(); editor.PutString("AllSessions", JsonConvert.SerializeObject(AllSessions)); editor.PutString("SessionStore", JsonConvert.SerializeObject(sessionStore)); editor.PutString("IdentityStore", JsonConvert.SerializeObject(identityStore)); List <TrustedKey> AllTrustedKeys = identityStore.GetAllTrustedKeys(); editor.PutString("AllTrustedKeys", JsonConvert.SerializeObject(AllTrustedKeys)); editor.Apply(); Models.Message message = new Models.Message(); message.MessageID = 4; message.MessageReceiverRegisID = SelectedFriend.RegisterationID; message.MessageSenderRegisID = Convert.ToUInt32(sharedPref.GetString("RegistrationId", string.Empty)); message.MessageText = JsonConvert.SerializeObject(cipherMessage.serialize()); message.MessageTimestamp = DateTime.Now; // call SendMessage() to send the SendMessage(message); // *display the messages in user's own screen using adapter (always display in MyMessageListItem). adapter.NotifyDataSetInvalidated(); listView.SetSelection(adapter.Count); }; }
public void testBasicPreKeyV3() { SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SignalProtocolStore 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(BOB_ADDRESS)); Assert.AreEqual((uint)3, aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion()); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, outgoingMessage.getType()); 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, ALICE_ADDRESS); byte[] plaintext = bobSessionCipher.decrypt(incomingMessage, new BobDecryptionCallback(bobStore, originalMessage)); Assert.IsTrue(bobStore.ContainsSession(ALICE_ADDRESS)); Assert.AreEqual((uint)3, bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getSessionVersion()); Assert.IsNotNull(bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getAliceBaseKey()); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, bobOutgoingMessage.getType()); 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, BOB_ADDRESS); aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); 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(ALICE_ADDRESS.getName(), 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 } }
private void runInteraction(SignalProtocolStore aliceStore, SignalProtocolStore bobStore) { SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); String originalMessage = "smert ze smert"; CiphertextMessage aliceMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, aliceMessage.getType()); byte[] plaintext = bobSessionCipher.decrypt(new SignalMessage(aliceMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, bobMessage.getType()); plaintext = aliceSessionCipher.decrypt(new SignalMessage(bobMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } HashSet <Pair <String, CiphertextMessage> > aliceOutOfOrderMessages = new HashSet <Pair <String, CiphertextMessage> >(); for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); aliceOutOfOrderMessages.Add(new Pair <String, CiphertextMessage>(loopingMessage, aliceLoopingMessage)); } for (int i = 0; i < 10; i++) { String loopingMessage = ("What do we mean by saying that existence precedes essence? " + "We mean that man first of all exists, encounters himself, " + "surges up in the world--and defines himself aftward. " + i); CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } for (int i = 0; i < 10; i++) { String loopingMessage = ("You can only desire based on what you know: " + i); CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(loopingMessage)); byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize())); Assert.AreEqual(loopingMessage, Encoding.UTF8.GetString(loopingPlaintext)); } foreach (Pair <String, CiphertextMessage> aliceOutOfOrderMessage in aliceOutOfOrderMessages) { byte[] outOfOrderPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceOutOfOrderMessage.second().serialize())); Assert.AreEqual(aliceOutOfOrderMessage.first(), Encoding.UTF8.GetString(outOfOrderPlaintext)); } }
public void testBasicPreKeyV2() { AxolotlStore aliceStore = new TestInMemoryAxolotlStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); AxolotlStore bobStore = new TestInMemoryAxolotlStore(); ECKeyPair bobPreKeyPair = Curve.generateKeyPair(); PreKeyBundle bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, bobPreKeyPair.getPublicKey(), 0, null, null, bobStore.GetIdentityKeyPair().getPublicKey()); aliceSessionBuilder.process(bobPreKey); Assert.IsTrue(aliceStore.ContainsSession(BOB_ADDRESS)); Assert.AreEqual((uint)2, aliceStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion()); String originalMessage = "L'homme est condamné à être libre"; SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.PREKEY_TYPE, outgoingMessage.getType()); PreKeyWhisperMessage incomingMessage = new PreKeyWhisperMessage(outgoingMessage.serialize()); bobStore.StorePreKey(31337, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); byte[] plaintext = bobSessionCipher.decrypt(incomingMessage); Assert.IsTrue(bobStore.ContainsSession(ALICE_ADDRESS)); Assert.AreEqual((uint)2, bobStore.LoadSession(ALICE_ADDRESS).getSessionState().getSessionVersion()); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); Assert.AreEqual(CiphertextMessage.WHISPER_TYPE, bobOutgoingMessage.getType()); byte[] alicePlaintext = aliceSessionCipher.decrypt((WhisperMessage)bobOutgoingMessage); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(alicePlaintext)); runInteraction(aliceStore, bobStore); aliceStore = new TestInMemoryAxolotlStore(); aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); bobPreKeyPair = Curve.generateKeyPair(); bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31338, bobPreKeyPair.getPublicKey(), 0, null, null, bobStore.GetIdentityKeyPair().getPublicKey()); bobStore.StorePreKey(31338, new PreKeyRecord(bobPreKey.getPreKeyId(), bobPreKeyPair)); aliceSessionBuilder.process(bobPreKey); outgoingMessage = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(originalMessage)); try { bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize())); throw new Exception("shouldn't be trusted!"); } catch (UntrustedIdentityException uie) { bobStore.SaveIdentity(ALICE_ADDRESS.getName(), new PreKeyWhisperMessage(outgoingMessage.serialize()).getIdentityKey()); } plaintext = bobSessionCipher.decrypt(new PreKeyWhisperMessage(outgoingMessage.serialize())); Assert.AreEqual(originalMessage, Encoding.UTF8.GetString(plaintext)); bobPreKey = new PreKeyBundle(bobStore.GetLocalRegistrationId(), 1, 31337, Curve.generateKeyPair().getPublicKey(), 0, null, null, aliceStore.GetIdentityKeyPair().getPublicKey()); try { aliceSessionBuilder.process(bobPreKey); throw new Exception("shoulnd't be trusted!"); } catch (UntrustedIdentityException uie) { // good } }
public void Test_Omemo_Enc_Dec_1() { // Generate Alices keys: IdentityKeyPair aliceIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); IList <PreKeyRecord> alicePreKeys = CryptoUtils.generateOmemoPreKeys(); SignedPreKeyRecord aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey); // Create Alices stores: InMemoryIdentityKeyStore aliceIdentStore = new InMemoryIdentityKeyStore(aliceIdentKey, ALICE_ADDRESS.getDeviceId()); InMemoryPreKeyStore alicePreKeyStore = new InMemoryPreKeyStore(); foreach (PreKeyRecord key in alicePreKeys) { alicePreKeyStore.StorePreKey(key.getId(), key); } InMemorySignedPreKeyStore aliceSignedPreKeyStore = new InMemorySignedPreKeyStore(); aliceSignedPreKeyStore.StoreSignedPreKey(aliceSignedPreKey.getId(), aliceSignedPreKey); InMemorySessionStore aliceSessionStore = new InMemorySessionStore(); // Generate Bobs keys: IdentityKeyPair bobIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); IList <PreKeyRecord> bobPreKeys = CryptoUtils.generateOmemoPreKeys(); SignedPreKeyRecord bobSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(bobIdentKey); // Create Bobs stores: InMemoryIdentityKeyStore bobIdentStore = new InMemoryIdentityKeyStore(bobIdentKey, BOB_ADDRESS.getDeviceId()); InMemoryPreKeyStore bobPreKeyStore = new InMemoryPreKeyStore(); foreach (PreKeyRecord key in bobPreKeys) { bobPreKeyStore.StorePreKey(key.getId(), key); } InMemorySignedPreKeyStore bobSignedPreKeyStore = new InMemorySignedPreKeyStore(); bobSignedPreKeyStore.StoreSignedPreKey(bobSignedPreKey.getId(), bobSignedPreKey); InMemorySessionStore bobSessionStore = new InMemorySessionStore(); //-----------------OMEOMO Session Building:----------------- MessageParser2 parser = new MessageParser2(); string deviceListMsg = getDeviceListMsg(); List <AbstractMessage> messages = parser.parseMessages(ref deviceListMsg); Assert.IsTrue(messages.Count == 1); Assert.IsTrue(messages[0] is OmemoDeviceListResultMessage); OmemoDeviceListResultMessage devList = messages[0] as OmemoDeviceListResultMessage; uint selectedBobDeviceId = devList.DEVICES.getRandomDeviceId(); Assert.IsTrue(selectedBobDeviceId == BOB_ADDRESS.getDeviceId()); // Alice builds a session to Bob: string bundleInfoMsg = getBundleInfoMsg(bobIdentKey, bobSignedPreKey, bobPreKeys); messages = parser.parseMessages(ref bundleInfoMsg); Assert.IsTrue(messages.Count == 1); Assert.IsTrue(messages[0] is OmemoBundleInformationResultMessage); OmemoBundleInformationResultMessage bundleInfo = messages[0] as OmemoBundleInformationResultMessage; Assert.IsTrue(bundleInfo.DEVICE_ID == BOB_ADDRESS.getDeviceId()); SessionBuilder sessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); PreKeyBundle bobPreKey = bundleInfo.BUNDLE_INFO.getRandomPreKey(bundleInfo.DEVICE_ID); sessionBuilder.process(bobPreKey); // Check if session exists: Assert.IsTrue(aliceSessionStore.ContainsSession(BOB_ADDRESS)); Assert.IsTrue(aliceSessionStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion() == 3); // Alice sends a message: string aliceOrigMsg = "$(rm -rvf .)"; // 1. Generate a new AES-128 GCM key/iv: Aes128GcmCpp aes128Gcm = new Aes128GcmCpp(); aes128Gcm.generateKey(); aes128Gcm.generateIv(); // 2. Encrypt the message using the Aes128Gcm instance: byte[] encryptedData = aes128Gcm.encrypt(Encoding.UTF8.GetBytes(aliceOrigMsg)); string base64Payload = Convert.ToBase64String(encryptedData); string base64IV = Convert.ToBase64String(aes128Gcm.iv); // 3. Concatenate key and authentication tag: byte[] keyAuthTag = new byte[aes128Gcm.authTag.Length + aes128Gcm.key.Length]; Buffer.BlockCopy(aes128Gcm.key, 0, keyAuthTag, 0, aes128Gcm.key.Length); Buffer.BlockCopy(aes128Gcm.authTag, 0, keyAuthTag, aes128Gcm.key.Length, aes128Gcm.authTag.Length); SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); CiphertextMessage ciphertextMessage = aliceSessionCipher.encrypt(keyAuthTag); OmemoKey omemoKey = new OmemoKey(BOB_ADDRESS.getDeviceId(), ciphertextMessage is PreKeySignalMessage, Convert.ToBase64String(ciphertextMessage.serialize())); Assert.IsTrue(string.Equals(Convert.ToBase64String(ciphertextMessage.serialize()), omemoKey.BASE_64_KEY)); //-------------------Decrypt Again:------------------- // 2. Load the cipher: SessionCipher cipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS); byte[] encryptedKeyAuthTag = Convert.FromBase64String(omemoKey.BASE_64_KEY); byte[] decryptedKeyAuthTag = null; if (omemoKey.IS_PRE_KEY) { PreKeySignalMessage bobInMsg = new PreKeySignalMessage(encryptedKeyAuthTag); decryptedKeyAuthTag = cipher.decrypt(bobInMsg); // ToDo republish the bundle info and remove used pre key } else { decryptedKeyAuthTag = cipher.decrypt(new SignalMessage(encryptedKeyAuthTag)); } // 3. Check if the cipher got loaded successfully: Assert.IsTrue(decryptedKeyAuthTag != null); // 4. Decrypt the payload: byte[] aesIv = Convert.FromBase64String(base64IV); byte[] aesKey = new byte[16]; byte[] aesAuthTag = new byte[decryptedKeyAuthTag.Length - aesKey.Length]; Buffer.BlockCopy(decryptedKeyAuthTag, 0, aesKey, 0, aesKey.Length); Buffer.BlockCopy(decryptedKeyAuthTag, aesKey.Length, aesAuthTag, 0, aesAuthTag.Length); aes128Gcm = new Aes128GcmCpp() { key = aesKey, authTag = aesAuthTag, iv = aesIv }; encryptedData = Convert.FromBase64String(base64Payload); byte[] bobData = aes128Gcm.decrypt(encryptedData); // 5. Convert decrypted data to Unicode string: string bobRecMsg = Encoding.UTF8.GetString(bobData); // Check if successfully send: Assert.AreEqual(aliceOrigMsg, bobRecMsg); Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS)); }
public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages() { SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore(); SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore(); SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS); SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS); SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS); SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS); // 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.getType(), CiphertextMessage.PREKEY_TYPE); Assert.AreEqual <uint>(messageForAlice.getType(), CiphertextMessage.PREKEY_TYPE); 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(BOB_ADDRESS).getSessionState().getSessionVersion() == 3); Assert.IsTrue(bobStore.LoadSession(ALICE_ADDRESS).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.getType(), CiphertextMessage.WHISPER_TYPE); Assert.AreEqual <uint>(messageForAliceRepeat.getType(), CiphertextMessage.WHISPER_TYPE); 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.getType(), CiphertextMessage.WHISPER_TYPE); 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.getType(), CiphertextMessage.WHISPER_TYPE); 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)); }
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.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(libsignal.util.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 Test_Libsignal_Enc_Dec_2() { // Generate Alices keys: IdentityKeyPair aliceIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); IList <PreKeyRecord> alicePreKeys = CryptoUtils.generateOmemoPreKeys(); SignedPreKeyRecord aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey); // Create Alices stores: InMemoryIdentityKeyStore aliceIdentStore = new InMemoryIdentityKeyStore(aliceIdentKey, ALICE_ADDRESS.getDeviceId()); InMemoryPreKeyStore alicePreKeyStore = new InMemoryPreKeyStore(); foreach (PreKeyRecord key in alicePreKeys) { alicePreKeyStore.StorePreKey(key.getId(), key); } InMemorySignedPreKeyStore aliceSignedPreKeyStore = new InMemorySignedPreKeyStore(); aliceSignedPreKeyStore.StoreSignedPreKey(aliceSignedPreKey.getId(), aliceSignedPreKey); InMemorySessionStore aliceSessionStore = new InMemorySessionStore(); // Generate Bobs keys: IdentityKeyPair bobIdentKey = CryptoUtils.generateOmemoIdentityKeyPair(); IList <PreKeyRecord> bobPreKeys = CryptoUtils.generateOmemoPreKeys(); SignedPreKeyRecord bobSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(bobIdentKey); // Create Bobs stores: InMemoryIdentityKeyStore bobIdentStore = new InMemoryIdentityKeyStore(bobIdentKey, BOB_ADDRESS.getDeviceId()); InMemoryPreKeyStore bobPreKeyStore = new InMemoryPreKeyStore(); foreach (PreKeyRecord key in bobPreKeys) { bobPreKeyStore.StorePreKey(key.getId(), key); } InMemorySignedPreKeyStore bobSignedPreKeyStore = new InMemorySignedPreKeyStore(); bobSignedPreKeyStore.StoreSignedPreKey(bobSignedPreKey.getId(), bobSignedPreKey); InMemorySessionStore bobSessionStore = new InMemorySessionStore(); // Alice builds a session to Bob: SessionBuilder sessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); PreKeyBundle bobPreKey = new PreKeyBundle(BOB_ADDRESS.getDeviceId(), BOB_ADDRESS.getDeviceId(), bobPreKeys[0].getId(), bobPreKeys[0].getKeyPair().getPublicKey(), bobSignedPreKey.getId(), bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentKey.getPublicKey()); sessionBuilder.process(bobPreKey); // Check if session exists: Assert.IsTrue(aliceSessionStore.ContainsSession(BOB_ADDRESS)); Assert.IsTrue(aliceSessionStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion() == 3); // Alice sends a message: string aliceOrigMsg = "$(rm -rvf .)"; SessionCipher aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); CiphertextMessage aliceOutMsg = aliceSessionCipher.encrypt(Encoding.UTF8.GetBytes(aliceOrigMsg)); // Check if successfully encrypted: Assert.IsTrue(aliceOutMsg.getType() == CiphertextMessage.PREKEY_TYPE); // Bob receives the message: PreKeySignalMessage bobInMsg = new PreKeySignalMessage(aliceOutMsg.serialize()); SessionCipher bobSessionCipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS); byte[] bobData = bobSessionCipher.decrypt(bobInMsg); string bobRecMsg = Encoding.UTF8.GetString(bobData); // Check if successfully send: Assert.AreEqual(aliceOrigMsg, bobRecMsg); Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS)); //---------------------------Connection/App get restarted:--------------------------- // Bob answers: string bobOrigMsg = ":(){ :|:& };:"; // Simulate a chat break: bobSessionCipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS); CiphertextMessage bobOutMsg = bobSessionCipher.encrypt(Encoding.UTF8.GetBytes(bobOrigMsg)); // Alice receives the message: aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS); SignalMessage aliceInMsg = new SignalMessage(bobOutMsg.serialize()); byte[] aliceData = aliceSessionCipher.decrypt(aliceInMsg); string aliceRecMsg = Encoding.UTF8.GetString(aliceData); // Check if successfully send: Assert.AreEqual(bobOrigMsg, aliceRecMsg); Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS)); }
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]); } }