Files
Android/src/org/thoughtcrime/securesms/crypto/KeyExchangeProcessor.java
Moxie Marlinspike 819982af7b 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.
2014-10-20 12:25:38 -07:00

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);
}
}