mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-08 02:42:07 +00:00
Support for multi-device.
1) In addition to the Recipient interface, there is now RecipientDevice. A Recipient can have multiple corresponding RecipientDevices. All addressing is done to a Recipient, but crypto sessions and transport delivery are done to RecipientDevice. 2) The Push transport handles the discovery and session setup of additional Recipient devices. 3) Some internal rejiggering of Groups.
This commit is contained in:
@@ -46,7 +46,9 @@ import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.SessionCipher;
|
||||
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
||||
import org.whispersystems.textsecure.storage.RecipientDevice;
|
||||
import org.whispersystems.textsecure.storage.Session;
|
||||
import org.whispersystems.textsecure.storage.SessionRecordV2;
|
||||
import org.whispersystems.textsecure.util.Hex;
|
||||
import org.whispersystems.textsecure.util.Util;
|
||||
|
||||
@@ -78,11 +80,12 @@ public class DecryptingQueue {
|
||||
}
|
||||
|
||||
public static void scheduleDecryption(Context context, MasterSecret masterSecret,
|
||||
long messageId, long threadId, String originator,
|
||||
long messageId, long threadId, String originator, int deviceId,
|
||||
String body, boolean isSecureMessage, boolean isKeyExchange)
|
||||
{
|
||||
DecryptionWorkItem runnable = new DecryptionWorkItem(context, masterSecret, messageId, threadId,
|
||||
originator, body, isSecureMessage, isKeyExchange);
|
||||
originator, deviceId, body,
|
||||
isSecureMessage, isKeyExchange);
|
||||
executor.execute(runnable);
|
||||
}
|
||||
|
||||
@@ -161,11 +164,13 @@ public class DecryptingQueue {
|
||||
long threadId = record.getThreadId();
|
||||
String body = record.getBody().getBody();
|
||||
String originator = record.getIndividualRecipient().getNumber();
|
||||
int originatorDeviceId = record.getRecipientDeviceId();
|
||||
boolean isSecureMessage = record.isSecure();
|
||||
boolean isKeyExchange = record.isKeyExchange();
|
||||
|
||||
scheduleDecryption(context, masterSecret, messageId, threadId,
|
||||
originator, body, isSecureMessage, isKeyExchange);
|
||||
originator, originatorDeviceId, body,
|
||||
isSecureMessage, isKeyExchange);
|
||||
}
|
||||
|
||||
private static class PushDecryptionWorkItem implements Runnable {
|
||||
@@ -186,15 +191,16 @@ public class DecryptingQueue {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, message.getSource(), false);
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, message.getSource(), false);
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSourceDevice());
|
||||
|
||||
if (!Session.hasSession(context, masterSecret, recipient)) {
|
||||
if (!SessionRecordV2.hasSession(context, masterSecret, recipientDevice)) {
|
||||
sendResult(PushReceiver.RESULT_NO_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
SessionCipher sessionCipher = SessionCipher.createFor(context, masterSecret, recipient);
|
||||
SessionCipher sessionCipher = SessionCipher.createFor(context, masterSecret, recipientDevice);
|
||||
byte[] plaintextBody = sessionCipher.decrypt(message.getBody());
|
||||
|
||||
message = message.withBody(plaintextBody);
|
||||
@@ -251,10 +257,11 @@ public class DecryptingQueue {
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
|
||||
try {
|
||||
String messageFrom = pdu.getFrom().getString();
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, messageFrom, false);
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
byte[] ciphertextPduBytes = getEncryptedData();
|
||||
String messageFrom = pdu.getFrom().getString();
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, messageFrom, false);
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), RecipientDevice.DEFAULT_DEVICE_ID);
|
||||
byte[] ciphertextPduBytes = getEncryptedData();
|
||||
|
||||
if (ciphertextPduBytes == null) {
|
||||
Log.w("DecryptingQueue", "No encoded PNG data found on parts.");
|
||||
@@ -272,7 +279,7 @@ public class DecryptingQueue {
|
||||
|
||||
Log.w("DecryptingQueue", "Decrypting: " + Hex.toString(ciphertextPduBytes));
|
||||
TextTransport transportDetails = new TextTransport();
|
||||
SessionCipher sessionCipher = SessionCipher.createFor(context, masterSecret, recipient);
|
||||
SessionCipher sessionCipher = SessionCipher.createFor(context, masterSecret, recipientDevice);
|
||||
byte[] decodedCiphertext = transportDetails.getDecodedMessage(ciphertextPduBytes);
|
||||
|
||||
try {
|
||||
@@ -322,11 +329,13 @@ public class DecryptingQueue {
|
||||
private final MasterSecret masterSecret;
|
||||
private final String body;
|
||||
private final String originator;
|
||||
private final int deviceId;
|
||||
private final boolean isSecureMessage;
|
||||
private final boolean isKeyExchange;
|
||||
|
||||
public DecryptionWorkItem(Context context, MasterSecret masterSecret, long messageId, long threadId,
|
||||
String originator, String body, boolean isSecureMessage, boolean isKeyExchange)
|
||||
String originator, int deviceId, String body, boolean isSecureMessage,
|
||||
boolean isKeyExchange)
|
||||
{
|
||||
this.context = context;
|
||||
this.messageId = messageId;
|
||||
@@ -334,6 +343,7 @@ public class DecryptingQueue {
|
||||
this.masterSecret = masterSecret;
|
||||
this.body = body;
|
||||
this.originator = originator;
|
||||
this.deviceId = deviceId;
|
||||
this.isSecureMessage = isSecureMessage;
|
||||
this.isKeyExchange = isKeyExchange;
|
||||
}
|
||||
@@ -343,8 +353,9 @@ public class DecryptingQueue {
|
||||
String plaintextBody;
|
||||
|
||||
try {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, originator, false);
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, originator, false);
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), deviceId);
|
||||
|
||||
if (!Session.hasSession(context, masterSecret, recipient)) {
|
||||
database.markAsNoSession(messageId);
|
||||
@@ -352,7 +363,7 @@ public class DecryptingQueue {
|
||||
}
|
||||
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
SessionCipher sessionCipher = SessionCipher.createFor(context, masterSecret, recipient);
|
||||
SessionCipher sessionCipher = SessionCipher.createFor(context, masterSecret, recipientDevice);
|
||||
byte[] decodedCiphertext = transportDetails.getDecodedMessage(body.getBytes());
|
||||
byte[] paddedPlaintext = sessionCipher.decrypt(decodedCiphertext);
|
||||
|
||||
@@ -401,9 +412,10 @@ public class DecryptingQueue {
|
||||
private void handleKeyExchangeProcessing(String plaintxtBody) {
|
||||
if (TextSecurePreferences.isAutoRespondKeyExchangeEnabled(context)) {
|
||||
try {
|
||||
Recipient recipient = new Recipient(null, originator, null, null);
|
||||
KeyExchangeMessage message = KeyExchangeMessage.createFor(plaintxtBody);
|
||||
KeyExchangeProcessor processor = KeyExchangeProcessor.createFor(context, masterSecret, recipient, message);
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, originator, false).getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), deviceId);
|
||||
KeyExchangeMessage message = KeyExchangeMessage.createFor(plaintxtBody);
|
||||
KeyExchangeProcessor processor = KeyExchangeProcessor.createFor(context, masterSecret, recipientDevice, message);
|
||||
|
||||
if (processor.isStale(message)) {
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsStaleKeyExchange(messageId);
|
||||
@@ -420,6 +432,9 @@ public class DecryptingQueue {
|
||||
} catch (InvalidMessageException e) {
|
||||
Log.w("DecryptingQueue", e);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsCorruptKeyExchange(messageId);
|
||||
} catch (RecipientFormattingException e) {
|
||||
Log.w("DecryptingQueue", e);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsCorruptKeyExchange(messageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.ecc.Curve;
|
||||
import org.whispersystems.textsecure.crypto.ecc.ECKeyPair;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.storage.RecipientDevice;
|
||||
import org.whispersystems.textsecure.storage.SessionRecordV2;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -70,8 +71,9 @@ public class KeyExchangeInitiator {
|
||||
identityKey.getPublicKey());
|
||||
|
||||
OutgoingKeyExchangeMessage textMessage = new OutgoingKeyExchangeMessage(recipient, message.serialize());
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), RecipientDevice.DEFAULT_DEVICE_ID);
|
||||
|
||||
SessionRecordV2 sessionRecordV2 = new SessionRecordV2(context, masterSecret, recipient);
|
||||
SessionRecordV2 sessionRecordV2 = new SessionRecordV2(context, masterSecret, recipientDevice);
|
||||
sessionRecordV2.setPendingKeyExchange(sequence, baseKey, ephemeralKey, identityKey);
|
||||
sessionRecordV2.save();
|
||||
|
||||
@@ -81,8 +83,9 @@ public class KeyExchangeInitiator {
|
||||
private static boolean hasInitiatedSession(Context context, MasterSecret masterSecret,
|
||||
Recipient recipient)
|
||||
{
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), RecipientDevice.DEFAULT_DEVICE_ID);
|
||||
return
|
||||
new SessionRecordV2(context, masterSecret, recipient)
|
||||
new SessionRecordV2(context, masterSecret, recipientDevice)
|
||||
.hasPendingKeyExchange();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,10 @@ import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.whispersystems.textsecure.crypto.InvalidMessageException;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.storage.RecipientDevice;
|
||||
|
||||
public abstract class KeyExchangeProcessor {
|
||||
|
||||
@@ -34,9 +36,13 @@ public abstract class KeyExchangeProcessor {
|
||||
throws InvalidMessageException;
|
||||
|
||||
public static KeyExchangeProcessor createFor(Context context, MasterSecret masterSecret,
|
||||
Recipient recipient, KeyExchangeMessage message)
|
||||
RecipientDevice recipientDevice,
|
||||
KeyExchangeMessage message)
|
||||
{
|
||||
if (message.isLegacy()) return new KeyExchangeProcessorV1(context, masterSecret, recipient);
|
||||
else return new KeyExchangeProcessorV2(context, masterSecret, recipient);
|
||||
if (message.isLegacy()) {
|
||||
return new KeyExchangeProcessorV1(context, masterSecret, recipientDevice.getRecipient());
|
||||
} else {
|
||||
return new KeyExchangeProcessorV2(context, masterSecret, recipientDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessage;
|
||||
import org.thoughtcrime.securesms.crypto.protocol.KeyExchangeMessageV1;
|
||||
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.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
|
||||
@@ -16,6 +17,7 @@ import org.whispersystems.textsecure.crypto.KeyPair;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.ecc.Curve;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.storage.CanonicalRecipient;
|
||||
import org.whispersystems.textsecure.storage.LocalKeyRecord;
|
||||
import org.whispersystems.textsecure.storage.RemoteKeyRecord;
|
||||
import org.whispersystems.textsecure.storage.SessionRecordV1;
|
||||
@@ -32,17 +34,17 @@ import java.security.SecureRandom;
|
||||
|
||||
public class KeyExchangeProcessorV1 extends KeyExchangeProcessor {
|
||||
|
||||
private Context context;
|
||||
private Recipient recipient;
|
||||
private MasterSecret masterSecret;
|
||||
private LocalKeyRecord localKeyRecord;
|
||||
private RemoteKeyRecord remoteKeyRecord;
|
||||
private SessionRecordV1 sessionRecord;
|
||||
private Context context;
|
||||
private CanonicalRecipient recipient;
|
||||
private MasterSecret masterSecret;
|
||||
private LocalKeyRecord localKeyRecord;
|
||||
private RemoteKeyRecord remoteKeyRecord;
|
||||
private SessionRecordV1 sessionRecord;
|
||||
|
||||
public KeyExchangeProcessorV1(Context context, MasterSecret masterSecret, Recipient recipient) {
|
||||
this.context = context;
|
||||
this.recipient = recipient;
|
||||
this.masterSecret = masterSecret;
|
||||
public KeyExchangeProcessorV1(Context context, MasterSecret masterSecret, CanonicalRecipient recipient) {
|
||||
this.context = context;
|
||||
this.recipient = recipient;
|
||||
this.masterSecret = masterSecret;
|
||||
|
||||
this.remoteKeyRecord = new RemoteKeyRecord(context, recipient);
|
||||
this.localKeyRecord = new LocalKeyRecord(context, masterSecret, recipient);
|
||||
@@ -55,7 +57,8 @@ public class KeyExchangeProcessorV1 extends KeyExchangeProcessor {
|
||||
}
|
||||
|
||||
public boolean isTrusted(IdentityKey identityKey) {
|
||||
return DatabaseFactory.getIdentityDatabase(context).isValidIdentity(masterSecret, recipient,
|
||||
return DatabaseFactory.getIdentityDatabase(context).isValidIdentity(masterSecret,
|
||||
recipient.getRecipientId(),
|
||||
identityKey);
|
||||
}
|
||||
|
||||
@@ -80,8 +83,13 @@ public class KeyExchangeProcessorV1 extends KeyExchangeProcessor {
|
||||
|
||||
@Override
|
||||
public void processKeyExchangeMessage(KeyExchangeMessage _message, long threadId) {
|
||||
KeyExchangeMessageV1 message = (KeyExchangeMessageV1)_message;
|
||||
int initiateKeyId = Conversions.lowBitsToMedium(message.getRemoteKey().getId());
|
||||
KeyExchangeMessageV1 message = (KeyExchangeMessageV1) _message;
|
||||
int initiateKeyId = Conversions.lowBitsToMedium(message.getRemoteKey().getId());
|
||||
|
||||
Recipient recipient = RecipientFactory.getRecipientsForIds(context,
|
||||
this.recipient.getRecipientId()+"",
|
||||
true).getPrimaryRecipient();
|
||||
|
||||
message.getRemoteKey().setId(initiateKeyId);
|
||||
|
||||
if (needsResponseFromUs()) {
|
||||
@@ -113,7 +121,7 @@ public class KeyExchangeProcessorV1 extends KeyExchangeProcessor {
|
||||
|
||||
if (message.hasIdentityKey()) {
|
||||
DatabaseFactory.getIdentityDatabase(context)
|
||||
.saveIdentity(masterSecret, recipient, message.getIdentityKey());
|
||||
.saveIdentity(masterSecret, recipient.getRecipientId(), message.getIdentityKey());
|
||||
}
|
||||
|
||||
DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
|
||||
@@ -130,7 +138,7 @@ public class KeyExchangeProcessorV1 extends KeyExchangeProcessor {
|
||||
|
||||
public LocalKeyRecord initializeRecordFor(Context context,
|
||||
MasterSecret masterSecret,
|
||||
Recipient recipient)
|
||||
CanonicalRecipient recipient)
|
||||
{
|
||||
Log.w("KeyExchangeProcessorV1", "Initializing local key pairs...");
|
||||
try {
|
||||
|
||||
@@ -8,6 +8,7 @@ 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.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
|
||||
@@ -24,6 +25,7 @@ import org.whispersystems.textsecure.crypto.ratchet.RatchetingSession;
|
||||
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.Session;
|
||||
import org.whispersystems.textsecure.storage.SessionRecordV2;
|
||||
import org.whispersystems.textsecure.util.Medium;
|
||||
@@ -37,15 +39,16 @@ import org.whispersystems.textsecure.util.Medium;
|
||||
public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
|
||||
private Context context;
|
||||
private Recipient recipient;
|
||||
private RecipientDevice recipientDevice;
|
||||
private MasterSecret masterSecret;
|
||||
private SessionRecordV2 sessionRecord;
|
||||
|
||||
public KeyExchangeProcessorV2(Context context, MasterSecret masterSecret, Recipient recipient) {
|
||||
public KeyExchangeProcessorV2(Context context, MasterSecret masterSecret, RecipientDevice recipientDevice)
|
||||
{
|
||||
this.context = context;
|
||||
this.recipient = recipient;
|
||||
this.recipientDevice = recipientDevice;
|
||||
this.masterSecret = masterSecret;
|
||||
this.sessionRecord = new SessionRecordV2(context, masterSecret, recipient);
|
||||
this.sessionRecord = new SessionRecordV2(context, masterSecret, recipientDevice);
|
||||
}
|
||||
|
||||
public boolean isTrusted(PreKeyWhisperMessage message) {
|
||||
@@ -57,7 +60,8 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
}
|
||||
|
||||
public boolean isTrusted(IdentityKey identityKey) {
|
||||
return DatabaseFactory.getIdentityDatabase(context).isValidIdentity(masterSecret, recipient,
|
||||
return DatabaseFactory.getIdentityDatabase(context).isValidIdentity(masterSecret,
|
||||
recipientDevice.getRecipientId(),
|
||||
identityKey);
|
||||
}
|
||||
|
||||
@@ -80,7 +84,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
|
||||
Log.w("KeyExchangeProcessor", "Received pre-key with local key ID: " + preKeyId);
|
||||
|
||||
if (!PreKeyRecord.hasRecord(context, preKeyId) && Session.hasSession(context, masterSecret, recipient)) {
|
||||
if (!PreKeyRecord.hasRecord(context, preKeyId) && SessionRecordV2.hasSession(context, masterSecret, recipientDevice)) {
|
||||
Log.w("KeyExchangeProcessor", "We've already processed the prekey part, letting bundled message fall through...");
|
||||
return;
|
||||
}
|
||||
@@ -97,7 +101,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
|
||||
RatchetingSession.initializeSession(sessionRecord, ourBaseKey, theirBaseKey, ourEphemeralKey,
|
||||
theirEphemeralKey, ourIdentityKey, theirIdentityKey);
|
||||
|
||||
Session.clearV1SessionFor(context, recipientDevice.getRecipient());
|
||||
sessionRecord.save();
|
||||
|
||||
if (preKeyId != Medium.MAX_VALUE) {
|
||||
@@ -105,7 +109,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
}
|
||||
|
||||
DatabaseFactory.getIdentityDatabase(context)
|
||||
.saveIdentity(masterSecret, recipient, theirIdentityKey);
|
||||
.saveIdentity(masterSecret, recipientDevice.getRecipientId(), theirIdentityKey);
|
||||
}
|
||||
|
||||
public void processKeyExchangeMessage(PreKeyEntity message, long threadId)
|
||||
@@ -129,7 +133,7 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
sessionRecord.save();
|
||||
|
||||
DatabaseFactory.getIdentityDatabase(context)
|
||||
.saveIdentity(masterSecret, recipient, message.getIdentityKey());
|
||||
.saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
|
||||
|
||||
broadcastSecurityUpdateEvent(context, threadId);
|
||||
}
|
||||
@@ -140,6 +144,10 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
{
|
||||
try {
|
||||
KeyExchangeMessageV2 message = (KeyExchangeMessageV2)_message;
|
||||
Recipient recipient = RecipientFactory.getRecipientsForIds(context,
|
||||
String.valueOf(recipientDevice.getRecipientId()),
|
||||
false)
|
||||
.getPrimaryRecipient();
|
||||
|
||||
Log.w("KeyExchangeProcessorV2", "Received key exchange with sequence: " + message.getSequence());
|
||||
|
||||
@@ -197,11 +205,11 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
ourIdentityKey, message.getIdentityKey());
|
||||
|
||||
sessionRecord.setSessionVersion(message.getVersion());
|
||||
Session.clearV1SessionFor(context, recipient);
|
||||
Session.clearV1SessionFor(context, recipientDevice.getRecipient());
|
||||
sessionRecord.save();
|
||||
|
||||
DatabaseFactory.getIdentityDatabase(context)
|
||||
.saveIdentity(masterSecret, recipient, message.getIdentityKey());
|
||||
.saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
|
||||
|
||||
DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user