diff --git a/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java b/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java
index ce6b07ba07..f4a06a553a 100644
--- a/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java
+++ b/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java
@@ -32,7 +32,6 @@ import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
-import org.thoughtcrime.securesms.crypto.KeyExchangeProcessorV2;
import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.recipients.Recipient;
@@ -148,19 +147,12 @@ public class ReceiveKeyActivity extends Activity {
}
private boolean isTrusted(KeyExchangeMessage message, PreKeyWhisperMessage messageBundle, IdentityKey identityUpdateMessage) {
- RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), recipientDeviceId);
+ RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), recipientDeviceId);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(this, masterSecret, recipientDevice);
- if (message != null) {
- KeyExchangeProcessor processor = KeyExchangeProcessor.createFor(this, masterSecret,
- recipientDevice, message);
- return processor.isTrusted(message);
- } else if (messageBundle != null) {
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(this, masterSecret, recipientDevice);
- return processor.isTrusted(messageBundle);
- } else if (identityUpdateMessage != null) {
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(this, masterSecret, recipientDevice);
- return processor.isTrusted(identityUpdateMessage);
- }
+ if (message != null) return processor.isTrusted(message);
+ else if (messageBundle != null) return processor.isTrusted(messageBundle);
+ else if (identityUpdateMessage != null) return processor.isTrusted(identityUpdateMessage);
return false;
}
@@ -186,7 +178,7 @@ public class ReceiveKeyActivity extends Activity {
} else if (getIntent().getBooleanExtra("is_identity_update", false)) {
this.identityUpdateMessage = new IdentityKey(Base64.decodeWithoutPadding(messageBody), 0);
} else {
- this.keyExchangeMessage = KeyExchangeMessage.createFor(messageBody);
+ this.keyExchangeMessage = new KeyExchangeMessage(messageBody);
}
} catch (IOException e) {
throw new AssertionError(e);
@@ -227,9 +219,13 @@ public class ReceiveKeyActivity extends Activity {
protected Void doInBackground(Void... params) {
if (keyExchangeMessage != null) {
try {
- RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), recipientDeviceId);
- KeyExchangeProcessor processor = KeyExchangeProcessor.createFor(ReceiveKeyActivity.this, masterSecret, recipientDevice, keyExchangeMessage);
+ RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(),
+ recipientDeviceId);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(ReceiveKeyActivity.this,
+ masterSecret, recipientDevice);
+
processor.processKeyExchangeMessage(keyExchangeMessage, threadId);
+
DatabaseFactory.getEncryptingSmsDatabase(ReceiveKeyActivity.this)
.markAsProcessedKeyExchange(messageId);
} catch (InvalidMessageException e) {
@@ -240,7 +236,7 @@ public class ReceiveKeyActivity extends Activity {
} else if (keyExchangeMessageBundle != null) {
try {
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), recipientDeviceId);
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(ReceiveKeyActivity.this,
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(ReceiveKeyActivity.this,
masterSecret, recipientDevice);
processor.processKeyExchangeMessage(keyExchangeMessageBundle);
diff --git a/src/org/thoughtcrime/securesms/crypto/DecryptingQueue.java b/src/org/thoughtcrime/securesms/crypto/DecryptingQueue.java
index f55b77b901..deb4c061b2 100644
--- a/src/org/thoughtcrime/securesms/crypto/DecryptingQueue.java
+++ b/src/org/thoughtcrime/securesms/crypto/DecryptingQueue.java
@@ -41,7 +41,6 @@ import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.sms.SmsTransportDetails;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libaxolotl.DuplicateMessageException;
-import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.libaxolotl.LegacyMessageException;
@@ -417,22 +416,20 @@ public class DecryptingQueue {
database.updateMessageBody(masterSecret, messageId, plaintextBody);
MessageNotifier.updateNotification(context, masterSecret);
- } catch (InvalidMessageException ime) {
+ } catch (InvalidMessageException | IOException ime) {
Log.w("DecryptionQueue", ime);
database.markAsDecryptFailed(messageId);
- } catch (IOException e) {
- Log.w("DecryptionQueue", e);
- database.markAsDecryptFailed(messageId);
}
}
private void handleKeyExchangeProcessing(String plaintextBody) {
if (TextSecurePreferences.isAutoRespondKeyExchangeEnabled(context)) {
try {
- Recipient recipient = RecipientFactory.getRecipientsFromString(context, originator, false).getPrimaryRecipient();
+ Recipient recipient = RecipientFactory.getRecipientsFromString(context, originator, false)
+ .getPrimaryRecipient();
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), deviceId);
- KeyExchangeMessage message = KeyExchangeMessage.createFor(plaintextBody);
- KeyExchangeProcessor processor = KeyExchangeProcessor.createFor(context, masterSecret, recipientDevice, message);
+ KeyExchangeMessage message = new KeyExchangeMessage(plaintextBody);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipientDevice);
if (processor.isStale(message)) {
DatabaseFactory.getEncryptingSmsDatabase(context).markAsStaleKeyExchange(messageId);
@@ -443,13 +440,7 @@ public class DecryptingQueue {
} catch (InvalidVersionException e) {
Log.w("DecryptingQueue", e);
DatabaseFactory.getEncryptingSmsDatabase(context).markAsInvalidVersionKeyExchange(messageId);
- } catch (InvalidKeyException e) {
- Log.w("DecryptingQueue", e);
- DatabaseFactory.getEncryptingSmsDatabase(context).markAsCorruptKeyExchange(messageId);
- } catch (InvalidMessageException e) {
- Log.w("DecryptingQueue", e);
- DatabaseFactory.getEncryptingSmsDatabase(context).markAsCorruptKeyExchange(messageId);
- } catch (RecipientFormattingException e) {
+ } catch (InvalidMessageException | RecipientFormattingException e) {
Log.w("DecryptingQueue", e);
DatabaseFactory.getEncryptingSmsDatabase(context).markAsCorruptKeyExchange(messageId);
} catch (LegacyMessageException e) {
diff --git a/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java b/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java
index 24abec36fe..ceb2dcd0f6 100644
--- a/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java
+++ b/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java
@@ -22,7 +22,7 @@ import android.content.Context;
import android.content.DialogInterface;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessageV2;
+import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
@@ -62,12 +62,12 @@ public class KeyExchangeInitiator {
private static void initiateKeyExchange(Context context, MasterSecret masterSecret, Recipient recipient) {
int sequence = getRandomSequence();
- int flags = KeyExchangeMessageV2.INITIATE_FLAG;
+ int flags = KeyExchangeMessage.INITIATE_FLAG;
ECKeyPair baseKey = Curve.generateKeyPair(true);
ECKeyPair ephemeralKey = Curve.generateKeyPair(true);
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
- KeyExchangeMessageV2 message = new KeyExchangeMessageV2(sequence, flags,
+ KeyExchangeMessage message = new KeyExchangeMessage(sequence, flags,
baseKey.getPublicKey(),
ephemeralKey.getPublicKey(),
identityKey.getPublicKey());
diff --git a/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessor.java b/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessor.java
index 165e957260..eeec9cf1ee 100644
--- a/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessor.java
+++ b/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessor.java
@@ -1,45 +1,254 @@
-/**
- * Copyright (C) 2011 Whisper Systems
- * Copyright (C) 2013 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
package org.thoughtcrime.securesms.crypto;
import android.content.Context;
import android.content.Intent;
+import android.util.Log;
import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.service.KeyCachingService;
+import org.thoughtcrime.securesms.service.PreKeyService;
+import org.thoughtcrime.securesms.sms.MessageSender;
+import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+import org.whispersystems.libaxolotl.IdentityKey;
+import org.whispersystems.libaxolotl.IdentityKeyPair;
+import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
+import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
+import org.whispersystems.libaxolotl.state.SessionRecord;
+import org.whispersystems.libaxolotl.state.SessionStore;
import org.whispersystems.textsecure.crypto.MasterSecret;
+import org.whispersystems.textsecure.push.PreKeyEntity;
+import org.whispersystems.textsecure.storage.InvalidKeyIdException;
+import org.whispersystems.textsecure.storage.PreKeyRecord;
import org.whispersystems.textsecure.storage.RecipientDevice;
+import org.whispersystems.textsecure.storage.TextSecureSessionStore;
+import org.whispersystems.textsecure.util.Medium;
-public abstract class KeyExchangeProcessor {
+/**
+ * This class processes key exchange interactions.
+ *
+ * @author Moxie Marlinspike
+ */
+
+public class KeyExchangeProcessor {
public static final String SECURITY_UPDATE_EVENT = "org.thoughtcrime.securesms.KEY_EXCHANGE_UPDATE";
- public abstract boolean isStale(KeyExchangeMessage message);
- public abstract boolean isTrusted(KeyExchangeMessage message);
- public abstract void processKeyExchangeMessage(KeyExchangeMessage message, long threadid)
- throws InvalidMessageException;
+ private Context context;
+ private RecipientDevice recipientDevice;
+ private MasterSecret masterSecret;
+ private SessionStore sessionStore;
- public static KeyExchangeProcessor createFor(Context context, MasterSecret masterSecret,
- RecipientDevice recipientDevice,
- KeyExchangeMessage message)
+ public KeyExchangeProcessor(Context context, MasterSecret masterSecret, RecipientDevice recipientDevice)
{
- return new KeyExchangeProcessorV2(context, masterSecret, recipientDevice);
+ this.context = context;
+ this.recipientDevice = recipientDevice;
+ this.masterSecret = masterSecret;
+ this.sessionStore = new TextSecureSessionStore(context, masterSecret);
+ }
+
+ public boolean isTrusted(PreKeyWhisperMessage message) {
+ return isTrusted(message.getIdentityKey());
+ }
+
+ public boolean isTrusted(PreKeyEntity entity) {
+ return isTrusted(entity.getIdentityKey());
+ }
+
+ public boolean isTrusted(KeyExchangeMessage message) {
+ return message.hasIdentityKey() && isTrusted(message.getIdentityKey());
+ }
+
+ public boolean isTrusted(IdentityKey identityKey) {
+ return DatabaseFactory.getIdentityDatabase(context).isValidIdentity(masterSecret,
+ recipientDevice.getRecipientId(),
+ identityKey);
+ }
+
+ public boolean isStale(KeyExchangeMessage message) {
+ SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
+ recipientDevice.getDeviceId());
+
+ return
+ message.isResponse() &&
+ (!sessionRecord.getSessionState().hasPendingKeyExchange() ||
+ sessionRecord.getSessionState().getPendingKeyExchangeSequence() != message.getSequence()) &&
+ !message.isResponseForSimultaneousInitiate();
+ }
+
+ public void processKeyExchangeMessage(PreKeyWhisperMessage message)
+ throws InvalidKeyIdException, InvalidKeyException
+ {
+ int preKeyId = message.getPreKeyId();
+ ECPublicKey theirBaseKey = message.getBaseKey();
+ ECPublicKey theirEphemeralKey = message.getWhisperMessage().getSenderEphemeral();
+ IdentityKey theirIdentityKey = message.getIdentityKey();
+
+ Log.w("KeyExchangeProcessor", "Received pre-key with local key ID: " + preKeyId);
+
+ if (!PreKeyRecord.hasRecord(context, preKeyId) &&
+ sessionStore.contains(recipientDevice.getRecipientId(), recipientDevice.getDeviceId()))
+ {
+ Log.w("KeyExchangeProcessor", "We've already processed the prekey part, letting bundled message fall through...");
+ return;
+ }
+
+ if (!PreKeyRecord.hasRecord(context, preKeyId))
+ throw new InvalidKeyIdException("No such prekey: " + preKeyId);
+
+ SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
+ recipientDevice.getDeviceId());
+ PreKeyRecord preKeyRecord = new PreKeyRecord(context, masterSecret, preKeyId);
+ ECKeyPair ourBaseKey = preKeyRecord.getKeyPair();
+ ECKeyPair ourEphemeralKey = ourBaseKey;
+ IdentityKeyPair ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
+ boolean simultaneousInitiate = sessionRecord.getSessionState().hasPendingPreKey();
+
+ if (!simultaneousInitiate) sessionRecord.reset();
+ else sessionRecord.archiveCurrentState();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(),
+ ourBaseKey, theirBaseKey,
+ ourEphemeralKey, theirEphemeralKey,
+ ourIdentityKey, theirIdentityKey);
+
+ sessionRecord.getSessionState().setLocalRegistrationId(TextSecurePreferences.getLocalRegistrationId(context));
+ sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId());
+
+ if (simultaneousInitiate) sessionRecord.getSessionState().setNeedsRefresh(true);
+
+ sessionStore.put(recipientDevice.getRecipientId(), recipientDevice.getDeviceId(), sessionRecord);
+
+ if (preKeyId != Medium.MAX_VALUE) {
+ PreKeyRecord.delete(context, preKeyId);
+ }
+
+ PreKeyService.initiateRefresh(context, masterSecret);
+
+ DatabaseFactory.getIdentityDatabase(context)
+ .saveIdentity(masterSecret, recipientDevice.getRecipientId(), theirIdentityKey);
+ }
+
+ public void processKeyExchangeMessage(PreKeyEntity message, long threadId)
+ throws InvalidKeyException
+ {
+ SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
+ recipientDevice.getDeviceId());
+ ECKeyPair ourBaseKey = Curve.generateKeyPair(true);
+ ECKeyPair ourEphemeralKey = Curve.generateKeyPair(true);
+ ECPublicKey theirBaseKey = message.getPublicKey();
+ ECPublicKey theirEphemeralKey = theirBaseKey;
+ IdentityKey theirIdentityKey = message.getIdentityKey();
+ IdentityKeyPair ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
+
+ if (sessionRecord.getSessionState().getNeedsRefresh()) sessionRecord.archiveCurrentState();
+ else sessionRecord.reset();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(),
+ ourBaseKey, theirBaseKey, ourEphemeralKey,
+ theirEphemeralKey, ourIdentityKey, theirIdentityKey);
+
+ sessionRecord.getSessionState().setPendingPreKey(message.getKeyId(), ourBaseKey.getPublicKey());
+ sessionRecord.getSessionState().setLocalRegistrationId(TextSecurePreferences.getLocalRegistrationId(context));
+ sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId());
+
+ sessionStore.put(recipientDevice.getRecipientId(), recipientDevice.getDeviceId(), sessionRecord);
+
+ DatabaseFactory.getIdentityDatabase(context)
+ .saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
+
+ if (threadId != -1) {
+ broadcastSecurityUpdateEvent(context, threadId);
+ }
+ }
+
+ public void processKeyExchangeMessage(KeyExchangeMessage message, long threadId)
+ throws InvalidMessageException
+ {
+ try {
+ SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
+ recipientDevice.getDeviceId());
+ Recipient recipient = RecipientFactory.getRecipientsForIds(context,
+ String.valueOf(recipientDevice.getRecipientId()),
+ false)
+ .getPrimaryRecipient();
+
+ Log.w("KeyExchangeProcessor", "Received key exchange with sequence: " + message.getSequence());
+
+ if (message.isInitiate()) {
+ ECKeyPair ourBaseKey, ourEphemeralKey;
+ IdentityKeyPair ourIdentityKey;
+
+ int flags = KeyExchangeMessage.RESPONSE_FLAG;
+
+ Log.w("KeyExchangeProcessor", "KeyExchange is an initiate.");
+
+ if (!sessionRecord.getSessionState().hasPendingKeyExchange()) {
+ Log.w("KeyExchangeProcessor", "We don't have a pending initiate...");
+ ourBaseKey = Curve.generateKeyPair(true);
+ ourEphemeralKey = Curve.generateKeyPair(true);
+ ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
+
+ sessionRecord.getSessionState().setPendingKeyExchange(message.getSequence(), ourBaseKey,
+ ourEphemeralKey, ourIdentityKey);
+ } else {
+ Log.w("KeyExchangeProcessor", "We alredy have a pending initiate, responding as simultaneous initiate...");
+ ourBaseKey = sessionRecord.getSessionState().getPendingKeyExchangeBaseKey();
+ ourEphemeralKey = sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey();
+ ourIdentityKey = sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey();
+ flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG;
+
+ sessionRecord.getSessionState().setPendingKeyExchange(message.getSequence(), ourBaseKey,
+ ourEphemeralKey, ourIdentityKey);
+ }
+
+ KeyExchangeMessage ourMessage = new KeyExchangeMessage(message.getSequence(),
+ flags, ourBaseKey.getPublicKey(),
+ ourEphemeralKey.getPublicKey(),
+ ourIdentityKey.getPublicKey());
+
+ OutgoingKeyExchangeMessage textMessage = new OutgoingKeyExchangeMessage(recipient,
+ ourMessage.serialize());
+ MessageSender.send(context, masterSecret, textMessage, threadId, true);
+ }
+
+ if (message.getSequence() != sessionRecord.getSessionState().getPendingKeyExchangeSequence()) {
+ Log.w("KeyExchangeProcessor", "No matching sequence for response. " +
+ "Is simultaneous initiate response: " + message.isResponseForSimultaneousInitiate());
+ return;
+ }
+
+ ECKeyPair ourBaseKey = sessionRecord.getSessionState().getPendingKeyExchangeBaseKey();
+ ECKeyPair ourEphemeralKey = sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey();
+ IdentityKeyPair ourIdentityKey = sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey();
+
+ sessionRecord.reset();
+
+ RatchetingSession.initializeSession(sessionRecord.getSessionState(),
+ ourBaseKey, message.getBaseKey(),
+ ourEphemeralKey, message.getEphemeralKey(),
+ ourIdentityKey, message.getIdentityKey());
+
+ sessionRecord.getSessionState().setSessionVersion(message.getVersion());
+ sessionStore.put(recipientDevice.getRecipientId(), recipientDevice.getDeviceId(), sessionRecord);
+
+ DatabaseFactory.getIdentityDatabase(context)
+ .saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
+
+ DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
+
+ broadcastSecurityUpdateEvent(context, threadId);
+ } catch (InvalidKeyException e) {
+ throw new InvalidMessageException(e);
+ }
}
public static void broadcastSecurityUpdateEvent(Context context, long threadId) {
@@ -49,4 +258,4 @@ public abstract class KeyExchangeProcessor {
context.sendBroadcast(intent, KeyCachingService.KEY_PERMISSION);
}
-}
\ No newline at end of file
+}
diff --git a/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java b/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java
deleted file mode 100644
index ab030a8857..0000000000
--- a/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessorV2.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package org.thoughtcrime.securesms.crypto;
-
-import android.content.Context;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
-import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessageV2;
-import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.service.PreKeyService;
-import org.thoughtcrime.securesms.sms.MessageSender;
-import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.libaxolotl.IdentityKey;
-import org.whispersystems.libaxolotl.IdentityKeyPair;
-import org.whispersystems.libaxolotl.InvalidKeyException;
-import org.whispersystems.libaxolotl.InvalidMessageException;
-import org.whispersystems.libaxolotl.ecc.Curve;
-import org.whispersystems.libaxolotl.ecc.ECKeyPair;
-import org.whispersystems.libaxolotl.ecc.ECPublicKey;
-import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
-import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
-import org.whispersystems.libaxolotl.state.SessionRecord;
-import org.whispersystems.libaxolotl.state.SessionStore;
-import org.whispersystems.textsecure.crypto.MasterSecret;
-import org.whispersystems.textsecure.push.PreKeyEntity;
-import org.whispersystems.textsecure.storage.InvalidKeyIdException;
-import org.whispersystems.textsecure.storage.PreKeyRecord;
-import org.whispersystems.textsecure.storage.RecipientDevice;
-import org.whispersystems.textsecure.storage.TextSecureSessionStore;
-import org.whispersystems.textsecure.util.Medium;
-
-/**
- * This class processes key exchange interactions.
- *
- * @author Moxie Marlinspike
- */
-
-public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
-
- private Context context;
- private RecipientDevice recipientDevice;
- private MasterSecret masterSecret;
- private SessionStore sessionStore;
-
- public KeyExchangeProcessorV2(Context context, MasterSecret masterSecret, RecipientDevice recipientDevice)
- {
- this.context = context;
- this.recipientDevice = recipientDevice;
- this.masterSecret = masterSecret;
- this.sessionStore = new TextSecureSessionStore(context, masterSecret);
- }
-
- public boolean isTrusted(PreKeyWhisperMessage message) {
- return isTrusted(message.getIdentityKey());
- }
-
- public boolean isTrusted(PreKeyEntity entity) {
- return isTrusted(entity.getIdentityKey());
- }
-
- public boolean isTrusted(KeyExchangeMessage message) {
- return message.hasIdentityKey() && isTrusted(message.getIdentityKey());
- }
-
- public boolean isTrusted(IdentityKey identityKey) {
- return DatabaseFactory.getIdentityDatabase(context).isValidIdentity(masterSecret,
- recipientDevice.getRecipientId(),
- identityKey);
- }
-
- public boolean isStale(KeyExchangeMessage m) {
- KeyExchangeMessageV2 message = (KeyExchangeMessageV2) m;
- SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
- recipientDevice.getDeviceId());
-
- return
- message.isResponse() &&
- (!sessionRecord.getSessionState().hasPendingKeyExchange() ||
- sessionRecord.getSessionState().getPendingKeyExchangeSequence() != message.getSequence()) &&
- !message.isResponseForSimultaneousInitiate();
- }
-
- public void processKeyExchangeMessage(PreKeyWhisperMessage message)
- throws InvalidKeyIdException, InvalidKeyException
- {
- int preKeyId = message.getPreKeyId();
- ECPublicKey theirBaseKey = message.getBaseKey();
- ECPublicKey theirEphemeralKey = message.getWhisperMessage().getSenderEphemeral();
- IdentityKey theirIdentityKey = message.getIdentityKey();
-
- Log.w("KeyExchangeProcessor", "Received pre-key with local key ID: " + preKeyId);
-
- if (!PreKeyRecord.hasRecord(context, preKeyId) &&
- sessionStore.contains(recipientDevice.getRecipientId(), recipientDevice.getDeviceId()))
- {
- Log.w("KeyExchangeProcessor", "We've already processed the prekey part, letting bundled message fall through...");
- return;
- }
-
- if (!PreKeyRecord.hasRecord(context, preKeyId))
- throw new InvalidKeyIdException("No such prekey: " + preKeyId);
-
- SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
- recipientDevice.getDeviceId());
- PreKeyRecord preKeyRecord = new PreKeyRecord(context, masterSecret, preKeyId);
- ECKeyPair ourBaseKey = preKeyRecord.getKeyPair();
- ECKeyPair ourEphemeralKey = ourBaseKey;
- IdentityKeyPair ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
- boolean simultaneousInitiate = sessionRecord.getSessionState().hasPendingPreKey();
-
- if (!simultaneousInitiate) sessionRecord.reset();
- else sessionRecord.archiveCurrentState();
-
- RatchetingSession.initializeSession(sessionRecord.getSessionState(),
- ourBaseKey, theirBaseKey,
- ourEphemeralKey, theirEphemeralKey,
- ourIdentityKey, theirIdentityKey);
-
- sessionRecord.getSessionState().setLocalRegistrationId(TextSecurePreferences.getLocalRegistrationId(context));
- sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId());
-
- if (simultaneousInitiate) sessionRecord.getSessionState().setNeedsRefresh(true);
-
- sessionStore.put(recipientDevice.getRecipientId(), recipientDevice.getDeviceId(), sessionRecord);
-
- if (preKeyId != Medium.MAX_VALUE) {
- PreKeyRecord.delete(context, preKeyId);
- }
-
- PreKeyService.initiateRefresh(context, masterSecret);
-
- DatabaseFactory.getIdentityDatabase(context)
- .saveIdentity(masterSecret, recipientDevice.getRecipientId(), theirIdentityKey);
- }
-
- public void processKeyExchangeMessage(PreKeyEntity message, long threadId)
- throws InvalidKeyException
- {
- SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
- recipientDevice.getDeviceId());
- ECKeyPair ourBaseKey = Curve.generateKeyPair(true);
- ECKeyPair ourEphemeralKey = Curve.generateKeyPair(true);
- ECPublicKey theirBaseKey = message.getPublicKey();
- ECPublicKey theirEphemeralKey = theirBaseKey;
- IdentityKey theirIdentityKey = message.getIdentityKey();
- IdentityKeyPair ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
-
- if (sessionRecord.getSessionState().getNeedsRefresh()) sessionRecord.archiveCurrentState();
- else sessionRecord.reset();
-
- RatchetingSession.initializeSession(sessionRecord.getSessionState(),
- ourBaseKey, theirBaseKey, ourEphemeralKey,
- theirEphemeralKey, ourIdentityKey, theirIdentityKey);
-
- sessionRecord.getSessionState().setPendingPreKey(message.getKeyId(), ourBaseKey.getPublicKey());
- sessionRecord.getSessionState().setLocalRegistrationId(TextSecurePreferences.getLocalRegistrationId(context));
- sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId());
-
- sessionStore.put(recipientDevice.getRecipientId(), recipientDevice.getDeviceId(), sessionRecord);
-
- DatabaseFactory.getIdentityDatabase(context)
- .saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
-
- if (threadId != -1) {
- broadcastSecurityUpdateEvent(context, threadId);
- }
- }
-
- @Override
- public void processKeyExchangeMessage(KeyExchangeMessage _message, long threadId)
- throws InvalidMessageException
- {
- try {
- KeyExchangeMessageV2 message = (KeyExchangeMessageV2) _message;
- SessionRecord sessionRecord = sessionStore.get(recipientDevice.getRecipientId(),
- recipientDevice.getDeviceId());
- Recipient recipient = RecipientFactory.getRecipientsForIds(context,
- String.valueOf(recipientDevice.getRecipientId()),
- false)
- .getPrimaryRecipient();
-
- Log.w("KeyExchangeProcessorV2", "Received key exchange with sequence: " + message.getSequence());
-
- if (message.isInitiate()) {
- ECKeyPair ourBaseKey, ourEphemeralKey;
- IdentityKeyPair ourIdentityKey;
-
- int flags = KeyExchangeMessageV2.RESPONSE_FLAG;
-
- Log.w("KeyExchangeProcessorV2", "KeyExchange is an initiate.");
-
- if (!sessionRecord.getSessionState().hasPendingKeyExchange()) {
- Log.w("KeyExchangeProcessorV2", "We don't have a pending initiate...");
- ourBaseKey = Curve.generateKeyPair(true);
- ourEphemeralKey = Curve.generateKeyPair(true);
- ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
-
- sessionRecord.getSessionState().setPendingKeyExchange(message.getSequence(), ourBaseKey,
- ourEphemeralKey, ourIdentityKey);
- } else {
- Log.w("KeyExchangeProcessorV2", "We alredy have a pending initiate, responding as simultaneous initiate...");
- ourBaseKey = sessionRecord.getSessionState().getPendingKeyExchangeBaseKey();
- ourEphemeralKey = sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey();
- ourIdentityKey = sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey();
- flags |= KeyExchangeMessageV2.SIMULTAENOUS_INITIATE_FLAG;
-
- sessionRecord.getSessionState().setPendingKeyExchange(message.getSequence(), ourBaseKey,
- ourEphemeralKey, ourIdentityKey);
- }
-
- KeyExchangeMessageV2 ourMessage = new KeyExchangeMessageV2(message.getSequence(),
- flags, ourBaseKey.getPublicKey(),
- ourEphemeralKey.getPublicKey(),
- ourIdentityKey.getPublicKey());
-
- OutgoingKeyExchangeMessage textMessage = new OutgoingKeyExchangeMessage(recipient,
- ourMessage.serialize());
- MessageSender.send(context, masterSecret, textMessage, threadId, false);
- }
-
- if (message.getSequence() != sessionRecord.getSessionState().getPendingKeyExchangeSequence()) {
- Log.w("KeyExchangeProcessorV2", "No matching sequence for response. " +
- "Is simultaneous initiate response: " + message.isResponseForSimultaneousInitiate());
- return;
- }
-
- ECKeyPair ourBaseKey = sessionRecord.getSessionState().getPendingKeyExchangeBaseKey();
- ECKeyPair ourEphemeralKey = sessionRecord.getSessionState().getPendingKeyExchangeEphemeralKey();
- IdentityKeyPair ourIdentityKey = sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey();
-
- sessionRecord.reset();
-
- RatchetingSession.initializeSession(sessionRecord.getSessionState(),
- ourBaseKey, message.getBaseKey(),
- ourEphemeralKey, message.getEphemeralKey(),
- ourIdentityKey, message.getIdentityKey());
-
- sessionRecord.getSessionState().setSessionVersion(message.getVersion());
- sessionStore.put(recipientDevice.getRecipientId(), recipientDevice.getDeviceId(), sessionRecord);
-
- DatabaseFactory.getIdentityDatabase(context)
- .saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
-
- DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
-
- broadcastSecurityUpdateEvent(context, threadId);
- } catch (InvalidKeyException e) {
- throw new InvalidMessageException(e);
- }
- }
-
-}
diff --git a/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessage.java b/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessage.java
index beef2064ec..c2a79cd840 100644
--- a/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessage.java
+++ b/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessage.java
@@ -1,38 +1,144 @@
-/**
- * Copyright (C) 2011 Whisper Systems
- * Copyright (C) 2013 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
package org.thoughtcrime.securesms.crypto.protocol;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.libaxolotl.LegacyMessageException;
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
+import org.whispersystems.libaxolotl.protocol.WhisperProtos;
+import org.whispersystems.textsecure.util.Base64;
+import org.whispersystems.textsecure.util.Conversions;
+import org.whispersystems.textsecure.util.Util;
-public abstract class KeyExchangeMessage {
- public abstract IdentityKey getIdentityKey();
- public abstract boolean hasIdentityKey();
- public abstract int getMaxVersion();
- public abstract int getVersion();
+import java.io.IOException;
- public static KeyExchangeMessage createFor(String rawMessage)
- throws InvalidMessageException, InvalidKeyException, InvalidVersionException, LegacyMessageException
+public class KeyExchangeMessage {
+
+ public static final int INITIATE_FLAG = 0x01;
+ public static final int RESPONSE_FLAG = 0X02;
+ public static final int SIMULTAENOUS_INITIATE_FLAG = 0x04;
+
+ private final int version;
+ private final int supportedVersion;
+ private final int sequence;
+ private final int flags;
+
+ private final ECPublicKey baseKey;
+ private final ECPublicKey ephemeralKey;
+ private final IdentityKey identityKey;
+ private final byte[] serialized;
+
+ public KeyExchangeMessage(int sequence, int flags,
+ ECPublicKey baseKey, ECPublicKey ephemeralKey,
+ IdentityKey identityKey)
{
- return new KeyExchangeMessageV2(rawMessage);
+ this.supportedVersion = CiphertextMessage.CURRENT_VERSION;
+ this.version = CiphertextMessage.CURRENT_VERSION;
+ this.sequence = sequence;
+ this.flags = flags;
+ this.baseKey = baseKey;
+ this.ephemeralKey = ephemeralKey;
+ this.identityKey = identityKey;
+
+ byte[] version = {Conversions.intsToByteHighAndLow(this.version, this.supportedVersion)};
+ byte[] message = WhisperProtos.KeyExchangeMessage.newBuilder()
+ .setId((sequence << 5) | flags)
+ .setBaseKey(ByteString.copyFrom(baseKey.serialize()))
+ .setEphemeralKey(ByteString.copyFrom(ephemeralKey.serialize()))
+ .setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
+ .build().toByteArray();
+
+ this.serialized = Util.combine(version, message);
}
-}
\ No newline at end of file
+
+ public KeyExchangeMessage(String serializedAndEncoded)
+ throws InvalidMessageException, InvalidVersionException, LegacyMessageException
+ {
+ try {
+ byte[] serialized = Base64.decodeWithoutPadding(serializedAndEncoded);
+ byte[][] parts = Util.split(serialized, 1, serialized.length - 1);
+
+ this.version = Conversions.highBitsToInt(parts[0][0]);
+ this.supportedVersion = Conversions.lowBitsToInt(parts[0][0]);
+
+ if (this.version <= CiphertextMessage.UNSUPPORTED_VERSION) {
+ throw new LegacyMessageException("Unsupported legacy version: " + this.version);
+ }
+
+ if (this.version > CiphertextMessage.CURRENT_VERSION) {
+ throw new InvalidVersionException("Unknown version: " + this.version);
+ }
+
+ WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.parseFrom(parts[1]);
+
+ if (!message.hasId() || !message.hasBaseKey() ||
+ !message.hasEphemeralKey() || !message.hasIdentityKey())
+ {
+ throw new InvalidMessageException("Some required fields missing!");
+ }
+
+ this.sequence = message.getId() >> 5;
+ this.flags = message.getId() & 0x1f;
+ this.serialized = serialized;
+ this.baseKey = Curve.decodePoint(message.getBaseKey().toByteArray(), 0);
+ this.ephemeralKey = Curve.decodePoint(message.getEphemeralKey().toByteArray(), 0);
+ this.identityKey = new IdentityKey(message.getIdentityKey().toByteArray(), 0);
+ } catch (InvalidKeyException | IOException e) {
+ throw new InvalidMessageException(e);
+ }
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public ECPublicKey getBaseKey() {
+ return baseKey;
+ }
+
+ public ECPublicKey getEphemeralKey() {
+ return ephemeralKey;
+ }
+
+ public IdentityKey getIdentityKey() {
+ return identityKey;
+ }
+
+ public boolean hasIdentityKey() {
+ return true;
+ }
+
+ public int getMaxVersion() {
+ return supportedVersion;
+ }
+
+ public boolean isResponse() {
+ return ((flags & RESPONSE_FLAG) != 0);
+ }
+
+ public boolean isInitiate() {
+ return (flags & INITIATE_FLAG) != 0;
+ }
+
+ public boolean isResponseForSimultaneousInitiate() {
+ return (flags & SIMULTAENOUS_INITIATE_FLAG) != 0;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public int getSequence() {
+ return sequence;
+ }
+
+ public String serialize() {
+ return Base64.encodeBytesWithoutPadding(serialized);
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessageV2.java b/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessageV2.java
deleted file mode 100644
index c8b74459f0..0000000000
--- a/src/org/thoughtcrime/securesms/crypto/protocol/KeyExchangeMessageV2.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.thoughtcrime.securesms.crypto.protocol;
-
-import com.google.protobuf.ByteString;
-import com.google.protobuf.InvalidProtocolBufferException;
-
-import org.whispersystems.libaxolotl.IdentityKey;
-import org.whispersystems.libaxolotl.InvalidKeyException;
-import org.whispersystems.libaxolotl.InvalidMessageException;
-import org.whispersystems.libaxolotl.InvalidVersionException;
-import org.whispersystems.libaxolotl.LegacyMessageException;
-import org.whispersystems.libaxolotl.ecc.Curve;
-import org.whispersystems.libaxolotl.ecc.ECPublicKey;
-import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
-import org.whispersystems.libaxolotl.protocol.WhisperProtos;
-import org.whispersystems.textsecure.util.Base64;
-import org.whispersystems.textsecure.util.Conversions;
-import org.whispersystems.textsecure.util.Util;
-
-import java.io.IOException;
-
-public class KeyExchangeMessageV2 extends KeyExchangeMessage {
-
- public static final int INITIATE_FLAG = 0x01;
- public static final int RESPONSE_FLAG = 0X02;
- public static final int SIMULTAENOUS_INITIATE_FLAG = 0x04;
-
- private final int version;
- private final int supportedVersion;
- private final int sequence;
- private final int flags;
-
- private final ECPublicKey baseKey;
- private final ECPublicKey ephemeralKey;
- private final IdentityKey identityKey;
- private final byte[] serialized;
-
- public KeyExchangeMessageV2(int sequence, int flags,
- ECPublicKey baseKey, ECPublicKey ephemeralKey,
- IdentityKey identityKey)
- {
- this.supportedVersion = CiphertextMessage.CURRENT_VERSION;
- this.version = CiphertextMessage.CURRENT_VERSION;
- this.sequence = sequence;
- this.flags = flags;
- this.baseKey = baseKey;
- this.ephemeralKey = ephemeralKey;
- this.identityKey = identityKey;
-
- byte[] version = {Conversions.intsToByteHighAndLow(this.version, this.supportedVersion)};
- byte[] message = WhisperProtos.KeyExchangeMessage.newBuilder()
- .setId((sequence << 5) | flags)
- .setBaseKey(ByteString.copyFrom(baseKey.serialize()))
- .setEphemeralKey(ByteString.copyFrom(ephemeralKey.serialize()))
- .setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
- .build().toByteArray();
-
- this.serialized = Util.combine(version, message);
- }
-
- public KeyExchangeMessageV2(String serializedAndEncoded)
- throws InvalidMessageException, InvalidVersionException, LegacyMessageException
- {
- try {
- byte[] serialized = Base64.decodeWithoutPadding(serializedAndEncoded);
- byte[][] parts = Util.split(serialized, 1, serialized.length - 1);
-
- this.version = Conversions.highBitsToInt(parts[0][0]);
- this.supportedVersion = Conversions.lowBitsToInt(parts[0][0]);
-
- if (this.version <= CiphertextMessage.UNSUPPORTED_VERSION) {
- throw new LegacyMessageException("Unsupported legacy version: " + this.version);
- }
-
- if (this.version > CiphertextMessage.CURRENT_VERSION) {
- throw new InvalidVersionException("Unknown version: " + this.version);
- }
-
- WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.parseFrom(parts[1]);
-
- if (!message.hasId() || !message.hasBaseKey() ||
- !message.hasEphemeralKey() || !message.hasIdentityKey())
- {
- throw new InvalidMessageException("Some required fields missing!");
- }
-
- this.sequence = message.getId() >> 5;
- this.flags = message.getId() & 0x1f;
- this.serialized = serialized;
- this.baseKey = Curve.decodePoint(message.getBaseKey().toByteArray(), 0);
- this.ephemeralKey = Curve.decodePoint(message.getEphemeralKey().toByteArray(), 0);
- this.identityKey = new IdentityKey(message.getIdentityKey().toByteArray(), 0);
- } catch (InvalidProtocolBufferException e) {
- throw new InvalidMessageException(e);
- } catch (InvalidKeyException e) {
- throw new InvalidMessageException(e);
- } catch (IOException e) {
- throw new InvalidMessageException(e);
- }
- }
-
- @Override
- public int getVersion() {
- return version;
- }
-
- public ECPublicKey getBaseKey() {
- return baseKey;
- }
-
- public ECPublicKey getEphemeralKey() {
- return ephemeralKey;
- }
-
- @Override
- public IdentityKey getIdentityKey() {
- return identityKey;
- }
-
- @Override
- public boolean hasIdentityKey() {
- return true;
- }
-
- @Override
- public int getMaxVersion() {
- return supportedVersion;
- }
-
- public boolean isResponse() {
- return ((flags & RESPONSE_FLAG) != 0);
- }
-
- public boolean isInitiate() {
- return (flags & INITIATE_FLAG) != 0;
- }
-
- public boolean isResponseForSimultaneousInitiate() {
- return (flags & SIMULTAENOUS_INITIATE_FLAG) != 0;
- }
-
- public int getFlags() {
- return flags;
- }
-
- public int getSequence() {
- return sequence;
- }
-
- public String serialize() {
- return Base64.encodeBytesWithoutPadding(serialized);
- }
-}
diff --git a/src/org/thoughtcrime/securesms/service/PushReceiver.java b/src/org/thoughtcrime/securesms/service/PushReceiver.java
index c0675d6be9..e9733f8fbd 100644
--- a/src/org/thoughtcrime/securesms/service/PushReceiver.java
+++ b/src/org/thoughtcrime/securesms/service/PushReceiver.java
@@ -9,7 +9,6 @@ import com.google.protobuf.InvalidProtocolBufferException;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
-import org.thoughtcrime.securesms.crypto.KeyExchangeProcessorV2;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
@@ -115,7 +114,7 @@ public class PushReceiver {
try {
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSource(), false).getPrimaryRecipient();
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSourceDevice());
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(context, masterSecret, recipientDevice);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipientDevice);
PreKeyWhisperMessage preKeyExchange = new PreKeyWhisperMessage(message.getBody());
if (processor.isTrusted(preKeyExchange)) {
diff --git a/src/org/thoughtcrime/securesms/service/SmsReceiver.java b/src/org/thoughtcrime/securesms/service/SmsReceiver.java
index 8b5cda76c2..2943255242 100644
--- a/src/org/thoughtcrime/securesms/service/SmsReceiver.java
+++ b/src/org/thoughtcrime/securesms/service/SmsReceiver.java
@@ -23,7 +23,6 @@ import android.util.Pair;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
-import org.thoughtcrime.securesms.crypto.KeyExchangeProcessorV2;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
import org.thoughtcrime.securesms.database.DatabaseFactory;
@@ -114,7 +113,7 @@ public class SmsReceiver {
try {
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSender(), false).getPrimaryRecipient();
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSenderDeviceId());
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(context, masterSecret, recipientDevice);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipientDevice);
SmsTransportDetails transportDetails = new SmsTransportDetails();
byte[] rawMessage = transportDetails.getDecodedMessage(message.getMessageBody().getBytes());
PreKeyWhisperMessage preKeyExchange = new PreKeyWhisperMessage(rawMessage);
@@ -127,7 +126,7 @@ public class SmsReceiver {
IncomingEncryptedMessage bundledMessage = new IncomingEncryptedMessage(message, bundledMessageBody);
Pair messageAndThreadId = storeSecureMessage(masterSecret, bundledMessage);
- Intent intent = new Intent(KeyExchangeProcessorV2.SECURITY_UPDATE_EVENT);
+ Intent intent = new Intent(KeyExchangeProcessor.SECURITY_UPDATE_EVENT);
intent.putExtra("thread_id", messageAndThreadId.second);
intent.setPackage(context.getPackageName());
context.sendBroadcast(intent, KeyCachingService.KEY_PERMISSION);
@@ -164,8 +163,8 @@ public class SmsReceiver {
try {
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSender(), false).getPrimaryRecipient();
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSenderDeviceId());
- KeyExchangeMessage exchangeMessage = KeyExchangeMessage.createFor(message.getMessageBody());
- KeyExchangeProcessor processor = KeyExchangeProcessor.createFor(context, masterSecret, recipientDevice, exchangeMessage);
+ KeyExchangeMessage exchangeMessage = new KeyExchangeMessage(message.getMessageBody());
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipientDevice);
if (processor.isStale(exchangeMessage)) {
message.setStale(true);
@@ -180,13 +179,7 @@ public class SmsReceiver {
} catch (InvalidVersionException e) {
Log.w("SmsReceiver", e);
message.setInvalidVersion(true);
- } catch (InvalidKeyException e) {
- Log.w("SmsReceiver", e);
- message.setCorrupted(true);
- } catch (InvalidMessageException e) {
- Log.w("SmsReceiver", e);
- message.setCorrupted(true);
- } catch (RecipientFormattingException e) {
+ } catch (InvalidMessageException | RecipientFormattingException e) {
Log.w("SmsReceiver", e);
message.setCorrupted(true);
} catch (LegacyMessageException e) {
diff --git a/src/org/thoughtcrime/securesms/transport/PushTransport.java b/src/org/thoughtcrime/securesms/transport/PushTransport.java
index 25a3950b89..39cb282286 100644
--- a/src/org/thoughtcrime/securesms/transport/PushTransport.java
+++ b/src/org/thoughtcrime/securesms/transport/PushTransport.java
@@ -23,7 +23,6 @@ import android.util.Log;
import com.google.protobuf.ByteString;
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
-import org.thoughtcrime.securesms.crypto.KeyExchangeProcessorV2;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
@@ -212,7 +211,7 @@ public class PushTransport extends BaseTransport {
for (int missingDeviceId : mismatchedDevices.getMissingDevices()) {
PushAddress address = PushAddress.create(context, recipientId, e164number, missingDeviceId);
PreKeyEntity preKey = socket.getPreKey(address);
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(context, masterSecret, address);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, address);
if (processor.isTrusted(preKey)) {
processor.processKeyExchangeMessage(preKey, threadId);
@@ -331,7 +330,7 @@ public class PushTransport extends BaseTransport {
for (PreKeyEntity preKey : preKeys) {
PushAddress device = PushAddress.create(context, pushAddress.getRecipientId(), pushAddress.getNumber(), preKey.getDeviceId());
- KeyExchangeProcessorV2 processor = new KeyExchangeProcessorV2(context, masterSecret, device);
+ KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, device);
if (processor.isTrusted(preKey)) {
processor.processKeyExchangeMessage(preKey, threadId);