mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 21:15:48 +00:00
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.
99 lines
4.2 KiB
Java
99 lines
4.2 KiB
Java
package org.thoughtcrime.securesms.crypto;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
|
|
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.OutgoingKeyExchangeMessage;
|
|
import org.whispersystems.libaxolotl.InvalidKeyException;
|
|
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
|
import org.whispersystems.libaxolotl.SessionBuilder;
|
|
import org.whispersystems.libaxolotl.StaleKeyExchangeException;
|
|
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
|
import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
|
|
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
|
|
import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
|
|
import org.whispersystems.libaxolotl.state.IdentityKeyStore;
|
|
import org.whispersystems.libaxolotl.state.PreKeyBundle;
|
|
import org.whispersystems.libaxolotl.state.PreKeyStore;
|
|
import org.whispersystems.libaxolotl.state.SessionStore;
|
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
|
import org.whispersystems.textsecure.storage.RecipientDevice;
|
|
import org.whispersystems.textsecure.storage.TextSecurePreKeyStore;
|
|
import org.whispersystems.textsecure.storage.TextSecureSessionStore;
|
|
import org.whispersystems.textsecure.util.Base64;
|
|
|
|
/**
|
|
* 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";
|
|
|
|
private Context context;
|
|
private RecipientDevice recipientDevice;
|
|
private MasterSecret masterSecret;
|
|
private SessionBuilder sessionBuilder;
|
|
|
|
public KeyExchangeProcessor(Context context, MasterSecret masterSecret, RecipientDevice recipientDevice)
|
|
{
|
|
this.context = context;
|
|
this.recipientDevice = recipientDevice;
|
|
this.masterSecret = masterSecret;
|
|
|
|
IdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context, masterSecret);
|
|
PreKeyStore preKeyStore = new TextSecurePreKeyStore(context, masterSecret);
|
|
SignedPreKeyStore signedPreKeyStore = new TextSecurePreKeyStore(context, masterSecret);
|
|
SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret);
|
|
|
|
this.sessionBuilder = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
|
|
identityKeyStore, recipientDevice.getRecipientId(),
|
|
recipientDevice.getDeviceId());
|
|
}
|
|
|
|
public void processKeyExchangeMessage(PreKeyBundle bundle, long threadId)
|
|
throws InvalidKeyException, UntrustedIdentityException
|
|
{
|
|
sessionBuilder.process(bundle);
|
|
|
|
if (threadId != -1) {
|
|
broadcastSecurityUpdateEvent(context, threadId);
|
|
}
|
|
}
|
|
|
|
public OutgoingKeyExchangeMessage processKeyExchangeMessage(KeyExchangeMessage message, long threadId)
|
|
throws InvalidKeyException, UntrustedIdentityException, StaleKeyExchangeException
|
|
{
|
|
KeyExchangeMessage responseMessage = sessionBuilder.process(message);
|
|
Recipient recipient = RecipientFactory.getRecipientsForIds(context,
|
|
String.valueOf(recipientDevice.getRecipientId()),
|
|
false)
|
|
.getPrimaryRecipient();
|
|
|
|
DecryptingQueue.scheduleRogueMessages(context, masterSecret, recipient);
|
|
|
|
broadcastSecurityUpdateEvent(context, threadId);
|
|
|
|
if (responseMessage != null) {
|
|
String serializedResponse = Base64.encodeBytesWithoutPadding(responseMessage.serialize());
|
|
return new OutgoingKeyExchangeMessage(recipient, serializedResponse);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static void broadcastSecurityUpdateEvent(Context context, long threadId) {
|
|
Intent intent = new Intent(SECURITY_UPDATE_EVENT);
|
|
intent.putExtra("thread_id", threadId);
|
|
intent.setPackage(context.getPackageName());
|
|
context.sendBroadcast(intent, KeyCachingService.KEY_PERMISSION);
|
|
}
|
|
|
|
}
|