mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-26 07:30:16 +00:00
Rearrange decrypt API.
1) Change SessionBuilder to only establish sessions via KeyExchangeMessage and PreKeyBundles. 2) Change SessionCipher to decrypt either WhisperMessage or PreKeyWhisperMessage items, automatically building a session for the latter. 3) Change SessionCipher to tear down new sessions built with PreKeyWhisperMessages if the embedded WhsiperMessage fails to decrypt.
This commit is contained in:
@@ -9,6 +9,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
|
||||
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
|
||||
import org.thoughtcrime.securesms.crypto.TextSecureCipher;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
@@ -24,16 +25,21 @@ import org.thoughtcrime.securesms.sms.IncomingKeyExchangeMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
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;
|
||||
import org.whispersystems.libaxolotl.NoSessionException;
|
||||
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
||||
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
|
||||
import org.whispersystems.libaxolotl.state.SessionStore;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.TransportDetails;
|
||||
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
||||
import org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
||||
import org.whispersystems.textsecure.push.PushTransportDetails;
|
||||
import org.whispersystems.textsecure.storage.RecipientDevice;
|
||||
import org.whispersystems.textsecure.storage.TextSecureSessionStore;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
@@ -113,34 +119,39 @@ public class PushReceiver {
|
||||
}
|
||||
|
||||
try {
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSource(), false).getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSourceDevice());
|
||||
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipientDevice);
|
||||
PreKeyWhisperMessage preKeyExchange = new PreKeyWhisperMessage(message.getBody());
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSource(), false).getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSourceDevice());
|
||||
PreKeyWhisperMessage preKeyWhisperMessage = new PreKeyWhisperMessage(message.getBody());
|
||||
TransportDetails transportDetails = new PushTransportDetails(preKeyWhisperMessage.getMessageVersion());
|
||||
TextSecureCipher cipher = new TextSecureCipher(context, masterSecret, recipientDevice, transportDetails);
|
||||
byte[] plaintext = cipher.decrypt(preKeyWhisperMessage);
|
||||
|
||||
try {
|
||||
processor.processKeyExchangeMessage(preKeyExchange);
|
||||
IncomingPushMessage bundledMessage = message.withBody(plaintext);
|
||||
handleReceivedMessage(masterSecret, bundledMessage, true);
|
||||
|
||||
IncomingPushMessage bundledMessage = message.withBody(preKeyExchange.getWhisperMessage().serialize());
|
||||
handleReceivedSecureMessage(masterSecret, bundledMessage);
|
||||
} catch (UntrustedIdentityException uie) {
|
||||
Log.w("PushReceiver", uie);
|
||||
String encoded = Base64.encodeBytes(message.getBody());
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(message, encoded, null);
|
||||
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, bundleMessage);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
}
|
||||
} catch (InvalidVersionException e) {
|
||||
Log.w("PushReceiver", e);
|
||||
handleReceivedCorruptedKey(masterSecret, message, true);
|
||||
} catch (InvalidKeyException | InvalidKeyIdException | InvalidMessageException |
|
||||
RecipientFormattingException e)
|
||||
RecipientFormattingException | LegacyMessageException e)
|
||||
{
|
||||
Log.w("PushReceiver", e);
|
||||
handleReceivedCorruptedKey(masterSecret, message, false);
|
||||
} catch (DuplicateMessageException e) {
|
||||
Log.w("PushReceiver", e);
|
||||
handleReceivedDuplicateMessage(message);
|
||||
} catch (NoSessionException e) {
|
||||
Log.w("PushReceiver", e);
|
||||
handleReceivedMessageForNoSession(masterSecret, message);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w("PushReceiver", e);
|
||||
String encoded = Base64.encodeBytes(message.getBody());
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(message, encoded, null);
|
||||
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
|
||||
Pair<Long, Long> messageAndThreadId = DatabaseFactory.getEncryptingSmsDatabase(context)
|
||||
.insertMessageInbox(masterSecret, bundleMessage);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.util.Pair;
|
||||
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
|
||||
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.crypto.TextSecureCipher;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
@@ -42,10 +43,12 @@ import org.thoughtcrime.securesms.sms.MultipartSmsMessageHandler;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
|
||||
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;
|
||||
import org.whispersystems.libaxolotl.NoSessionException;
|
||||
import org.whispersystems.libaxolotl.StaleKeyExchangeException;
|
||||
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
||||
import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
|
||||
@@ -115,39 +118,47 @@ public class SmsReceiver {
|
||||
IncomingPreKeyBundleMessage message)
|
||||
{
|
||||
Log.w("SmsReceiver", "Processing prekey message...");
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
|
||||
try {
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSender(), false).getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSenderDeviceId());
|
||||
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipientDevice);
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
byte[] rawMessage = transportDetails.getDecodedMessage(message.getMessageBody().getBytes());
|
||||
PreKeyWhisperMessage preKeyExchange = new PreKeyWhisperMessage(rawMessage);
|
||||
if (masterSecret != null) {
|
||||
try {
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSender(), false).getPrimaryRecipient();
|
||||
RecipientDevice recipientDevice = new RecipientDevice(recipient.getRecipientId(), message.getSenderDeviceId());
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
TextSecureCipher cipher = new TextSecureCipher(context, masterSecret, recipientDevice, transportDetails);
|
||||
byte[] rawMessage = transportDetails.getDecodedMessage(message.getMessageBody().getBytes());
|
||||
PreKeyWhisperMessage preKeyWhisperMessage = new PreKeyWhisperMessage(rawMessage);
|
||||
byte[] plaintext = cipher.decrypt(preKeyWhisperMessage);
|
||||
|
||||
processor.processKeyExchangeMessage(preKeyExchange);
|
||||
IncomingEncryptedMessage bundledMessage = new IncomingEncryptedMessage(message, new String(transportDetails.getEncodedMessage(preKeyWhisperMessage.getWhisperMessage().serialize())));
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, bundledMessage);
|
||||
|
||||
WhisperMessage ciphertextMessage = preKeyExchange.getWhisperMessage();
|
||||
String bundledMessageBody = new String(transportDetails.getEncodedMessage(ciphertextMessage.serialize()));
|
||||
IncomingEncryptedMessage bundledMessage = new IncomingEncryptedMessage(message, bundledMessageBody);
|
||||
Pair<Long, Long> messageAndThreadId = storeSecureMessage(masterSecret, bundledMessage);
|
||||
database.updateMessageBody(masterSecret, messageAndThreadId.first, new String(plaintext));
|
||||
|
||||
Intent intent = new Intent(KeyExchangeProcessor.SECURITY_UPDATE_EVENT);
|
||||
intent.putExtra("thread_id", messageAndThreadId.second);
|
||||
intent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(intent, KeyCachingService.KEY_PERMISSION);
|
||||
Intent intent = new Intent(KeyExchangeProcessor.SECURITY_UPDATE_EVENT);
|
||||
intent.putExtra("thread_id", messageAndThreadId.second);
|
||||
intent.setPackage(context.getPackageName());
|
||||
context.sendBroadcast(intent, KeyCachingService.KEY_PERMISSION);
|
||||
|
||||
return messageAndThreadId;
|
||||
} catch (InvalidKeyException | RecipientFormattingException | InvalidMessageException | IOException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setCorrupted(true);
|
||||
} catch (InvalidVersionException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setInvalidVersion(true);
|
||||
} catch (InvalidKeyIdException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setStale(true);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
return messageAndThreadId;
|
||||
} catch (InvalidKeyException | RecipientFormattingException | InvalidMessageException | IOException | NoSessionException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setCorrupted(true);
|
||||
} catch (InvalidVersionException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setInvalidVersion(true);
|
||||
} catch (InvalidKeyIdException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setStale(true);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
} catch (DuplicateMessageException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setDuplicate(true);
|
||||
} catch (LegacyMessageException e) {
|
||||
Log.w("SmsReceiver", e);
|
||||
message.setLegacyVersion(true);
|
||||
}
|
||||
}
|
||||
|
||||
return storeStandardMessage(masterSecret, message);
|
||||
|
||||
Reference in New Issue
Block a user