mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-20 15:10:51 +00:00
Refactor the ciphertext message parsing and building.
This commit is contained in:
@@ -40,6 +40,7 @@ import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.MemoryCleaner;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||
import org.whispersystems.textsecure.storage.InvalidKeyIdException;
|
||||
|
||||
@@ -182,9 +183,9 @@ public class ReceiveKeyActivity extends Activity {
|
||||
} else if (keyExchangeMessageBundle != null) {
|
||||
try {
|
||||
keyExchangeProcessor.processKeyExchangeMessage(keyExchangeMessageBundle);
|
||||
byte[] bundledMessage = keyExchangeMessageBundle.getBundledMessage();
|
||||
CiphertextMessage bundledMessage = keyExchangeMessageBundle.getBundledMessage();
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
String messageBody = new String(transportDetails.getEncodedMessage(bundledMessage));
|
||||
String messageBody = new String(transportDetails.getEncodedMessage(bundledMessage.serialize()));
|
||||
|
||||
DatabaseFactory.getEncryptingSmsDatabase(ReceiveKeyActivity.this)
|
||||
.updateBundleMessageBody(masterSecret, messageId, messageBody);
|
||||
@@ -196,6 +197,10 @@ public class ReceiveKeyActivity extends Activity {
|
||||
Log.w("ReceiveKeyActivity", e);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(ReceiveKeyActivity.this)
|
||||
.markAsCorruptKeyExchange(messageId);
|
||||
} catch (InvalidKeyException e) {
|
||||
Log.w("ReceiveKeyActivity", e);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(ReceiveKeyActivity.this)
|
||||
.markAsCorruptKeyExchange(messageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -48,7 +48,6 @@ import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||
import org.whispersystems.textsecure.crypto.SessionCipher;
|
||||
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
||||
import org.whispersystems.textsecure.push.PushTransportDetails;
|
||||
import org.whispersystems.textsecure.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -197,9 +196,9 @@ public class DecryptingQueue {
|
||||
}
|
||||
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey, new PushTransportDetails());
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey);
|
||||
byte[] plaintextBody = messageCipher.decrypt(recipient, message.getBody());
|
||||
|
||||
byte[] plaintextBody = messageCipher.decrypt(recipient, message.getBody());
|
||||
message = message.withBody(plaintextBody);
|
||||
sendResult(PushReceiver.RESULT_OK);
|
||||
} catch (InvalidMessageException e) {
|
||||
@@ -276,11 +275,13 @@ public class DecryptingQueue {
|
||||
|
||||
synchronized (SessionCipher.CIPHER_LOCK) {
|
||||
Log.w("DecryptingQueue", "Decrypting: " + Hex.toString(ciphertextPduBytes));
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher message = new MessageCipher(context, masterSecret, identityKey, new TextTransport());
|
||||
TextTransport transportDetails = new TextTransport();
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey);
|
||||
byte[] ciphertext = transportDetails.getDecodedMessage(ciphertextPduBytes);
|
||||
|
||||
try {
|
||||
plaintextPduBytes = message.decrypt(recipient, ciphertextPduBytes);
|
||||
plaintextPduBytes = messageCipher.decrypt(recipient, ciphertext);
|
||||
} catch (InvalidMessageException ime) {
|
||||
// XXX - For some reason, Sprint seems to append a single character to the
|
||||
// end of message text segments. I don't know why, so here we just try
|
||||
@@ -289,7 +290,8 @@ public class DecryptingQueue {
|
||||
Log.w("DecryptingQueue", "Attempting truncated decrypt...");
|
||||
byte[] truncated = new byte[ciphertextPduBytes.length - 1];
|
||||
System.arraycopy(ciphertextPduBytes, 0, truncated, 0, truncated.length);
|
||||
plaintextPduBytes = message.decrypt(recipient, truncated);
|
||||
ciphertext = transportDetails.getDecodedMessage(truncated);
|
||||
plaintextPduBytes = messageCipher.decrypt(recipient, ciphertext);
|
||||
} else {
|
||||
throw ime;
|
||||
}
|
||||
@@ -311,6 +313,9 @@ public class DecryptingQueue {
|
||||
} catch (MmsException mme) {
|
||||
Log.w("DecryptingQueue", mme);
|
||||
database.markAsDecryptFailed(messageId, threadId);
|
||||
} catch (IOException e) {
|
||||
Log.w("DecryptingQueue", e);
|
||||
database.markAsDecryptFailed(messageId, threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -354,10 +359,13 @@ public class DecryptingQueue {
|
||||
return;
|
||||
}
|
||||
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher message = new MessageCipher(context, masterSecret, identityKey, new SmsTransportDetails());
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey);
|
||||
byte[] ciphertext = transportDetails.getDecodedMessage(body.getBytes());
|
||||
byte[] paddedPlaintext = messageCipher.decrypt(recipient, ciphertext);
|
||||
|
||||
plaintextBody = new String(message.decrypt(recipient, body.getBytes()));
|
||||
plaintextBody = new String(transportDetails.getStrippedPaddingMessageBody(paddedPlaintext));
|
||||
} catch (InvalidMessageException e) {
|
||||
Log.w("DecryptionQueue", e);
|
||||
database.markAsDecryptFailed(messageId);
|
||||
@@ -366,6 +374,10 @@ public class DecryptingQueue {
|
||||
Log.w("DecryptionQueue", e);
|
||||
database.markAsDecryptFailed(messageId);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
Log.w("DecryptionQueue", e);
|
||||
database.markAsDecryptFailed(messageId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -22,12 +22,17 @@ 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.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
|
||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||
import org.whispersystems.textsecure.crypto.InvalidKeyException;
|
||||
import org.whispersystems.textsecure.crypto.KeyPair;
|
||||
import org.whispersystems.textsecure.crypto.KeyUtil;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||
import org.whispersystems.textsecure.crypto.PublicKey;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||
import org.whispersystems.textsecure.push.PreKeyEntity;
|
||||
import org.whispersystems.textsecure.storage.InvalidKeyIdException;
|
||||
@@ -35,10 +40,6 @@ import org.whispersystems.textsecure.storage.LocalKeyRecord;
|
||||
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
||||
import org.whispersystems.textsecure.storage.RemoteKeyRecord;
|
||||
import org.whispersystems.textsecure.storage.SessionRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage;
|
||||
import org.whispersystems.textsecure.util.Conversions;
|
||||
import org.whispersystems.textsecure.util.Medium;
|
||||
|
||||
@@ -103,7 +104,9 @@ public class KeyExchangeProcessor {
|
||||
(localKeyRecord.getCurrentKeyPair() != null && localKeyRecord.getCurrentKeyPair().getId() != responseKeyId);
|
||||
}
|
||||
|
||||
public void processKeyExchangeMessage(PreKeyBundleMessage message) throws InvalidKeyIdException {
|
||||
public void processKeyExchangeMessage(PreKeyBundleMessage message)
|
||||
throws InvalidKeyIdException, InvalidKeyException
|
||||
{
|
||||
int preKeyId = message.getPreKeyId();
|
||||
PublicKey remoteKey = message.getPublicKey();
|
||||
IdentityKey remoteIdentity = message.getIdentityKey();
|
||||
@@ -131,7 +134,7 @@ public class KeyExchangeProcessor {
|
||||
sessionRecord.setSessionId(localKeyRecord.getCurrentKeyPair().getPublicKey().getFingerprintBytes(),
|
||||
remoteKeyRecord.getCurrentRemoteKey().getFingerprintBytes());
|
||||
sessionRecord.setIdentityKey(remoteIdentity);
|
||||
sessionRecord.setSessionVersion(Math.min(message.getSupportedVersion(), MessageCipher.SUPPORTED_VERSION));
|
||||
sessionRecord.setSessionVersion(Math.min(message.getSupportedVersion(), PreKeyBundleMessage.SUPPORTED_VERSION));
|
||||
sessionRecord.setNegotiatedSessionVersion(sessionRecord.getSessionVersion());
|
||||
|
||||
localKeyRecord.save();
|
||||
@@ -159,8 +162,8 @@ public class KeyExchangeProcessor {
|
||||
sessionRecord.setSessionId(localKeyRecord.getCurrentKeyPair().getPublicKey().getFingerprintBytes(),
|
||||
remoteKeyRecord.getCurrentRemoteKey().getFingerprintBytes());
|
||||
sessionRecord.setIdentityKey(message.getIdentityKey());
|
||||
sessionRecord.setNegotiatedSessionVersion(MessageCipher.SUPPORTED_VERSION);
|
||||
sessionRecord.setSessionVersion(MessageCipher.SUPPORTED_VERSION);
|
||||
sessionRecord.setNegotiatedSessionVersion(CiphertextMessage.SUPPORTED_VERSION);
|
||||
sessionRecord.setSessionVersion(CiphertextMessage.SUPPORTED_VERSION);
|
||||
sessionRecord.setPrekeyBundleRequired(true);
|
||||
sessionRecord.save();
|
||||
|
||||
@@ -174,7 +177,7 @@ public class KeyExchangeProcessor {
|
||||
|
||||
if (needsResponseFromUs()) {
|
||||
localKeyRecord = KeyUtil.initializeRecordFor(recipient, context, masterSecret);
|
||||
KeyExchangeMessage ourMessage = new KeyExchangeMessage(context, masterSecret, Math.min(MessageCipher.SUPPORTED_VERSION, message.getMaxVersion()), localKeyRecord, initiateKeyId);
|
||||
KeyExchangeMessage ourMessage = new KeyExchangeMessage(context, masterSecret, Math.min(CiphertextMessage.SUPPORTED_VERSION, message.getMaxVersion()), localKeyRecord, initiateKeyId);
|
||||
OutgoingKeyExchangeMessage textMessage = new OutgoingKeyExchangeMessage(recipient, ourMessage.serialize());
|
||||
Log.w("KeyExchangeProcessor", "Responding with key exchange message fingerprint: " + ourMessage.getPublicKey().getFingerprint());
|
||||
Log.w("KeyExchangeProcessor", "Which has a local key record fingerprint: " + localKeyRecord.getCurrentKeyPair().getPublicKey().getFingerprint());
|
||||
@@ -188,10 +191,10 @@ public class KeyExchangeProcessor {
|
||||
sessionRecord.setSessionId(localKeyRecord.getCurrentKeyPair().getPublicKey().getFingerprintBytes(),
|
||||
remoteKeyRecord.getCurrentRemoteKey().getFingerprintBytes());
|
||||
sessionRecord.setIdentityKey(message.getIdentityKey());
|
||||
sessionRecord.setSessionVersion(Math.min(MessageCipher.SUPPORTED_VERSION, message.getMaxVersion()));
|
||||
sessionRecord.setSessionVersion(Math.min(CiphertextMessage.SUPPORTED_VERSION, message.getMaxVersion()));
|
||||
sessionRecord.setNegotiatedSessionVersion(sessionRecord.getSessionVersion());
|
||||
|
||||
Log.w("KeyExchangeUtil", "Setting session version: " + Math.min(MessageCipher.SUPPORTED_VERSION, message.getMaxVersion()));
|
||||
Log.w("KeyExchangeUtil", "Setting session version: " + Math.min(CiphertextMessage.SUPPORTED_VERSION, message.getMaxVersion()));
|
||||
|
||||
sessionRecord.save();
|
||||
|
||||
|
@@ -20,12 +20,12 @@ import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||
import org.whispersystems.textsecure.crypto.InvalidKeyException;
|
||||
import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||
import org.whispersystems.textsecure.crypto.PublicKey;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.storage.LocalKeyRecord;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
import org.whispersystems.textsecure.util.Conversions;
|
||||
@@ -59,6 +59,8 @@ import java.io.IOException;
|
||||
|
||||
public class KeyExchangeMessage {
|
||||
|
||||
private static final int SUPPORTED_VERSION = CiphertextMessage.SUPPORTED_VERSION;
|
||||
|
||||
private final int messageVersion;
|
||||
private final int supportedVersion;
|
||||
private final PublicKey publicKey;
|
||||
@@ -68,7 +70,7 @@ public class KeyExchangeMessage {
|
||||
public KeyExchangeMessage(Context context, MasterSecret masterSecret, int messageVersion, LocalKeyRecord record, int highIdBits) {
|
||||
this.publicKey = new PublicKey(record.getCurrentKeyPair().getPublicKey());
|
||||
this.messageVersion = messageVersion;
|
||||
this.supportedVersion = MessageCipher.SUPPORTED_VERSION;
|
||||
this.supportedVersion = SUPPORTED_VERSION;
|
||||
|
||||
publicKey.setId(publicKey.getId() | (highIdBits << 12));
|
||||
|
||||
@@ -100,9 +102,9 @@ public class KeyExchangeMessage {
|
||||
this.supportedVersion = Conversions.lowBitsToInt(keyBytes[0]);
|
||||
this.serialized = messageBody;
|
||||
|
||||
if (messageVersion > MessageCipher.SUPPORTED_VERSION)
|
||||
if (messageVersion > SUPPORTED_VERSION)
|
||||
throw new InvalidVersionException("Key exchange with version: " + messageVersion +
|
||||
" but we only support: " + MessageCipher.SUPPORTED_VERSION);
|
||||
" but we only support: " + SUPPORTED_VERSION);
|
||||
|
||||
if (messageVersion >= 1)
|
||||
keyBytes = Base64.decodeWithoutPadding(messageBody);
|
||||
|
@@ -6,6 +6,7 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
|
||||
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
@@ -21,7 +22,6 @@ import org.thoughtcrime.securesms.sms.IncomingKeyExchangeMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.sms.SmsTransportDetails;
|
||||
import org.thoughtcrime.securesms.transport.SmsTransport;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.textsecure.crypto.InvalidKeyException;
|
||||
import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
||||
@@ -99,7 +99,7 @@ public class PushReceiver {
|
||||
if (processor.isTrusted(preKeyExchange)) {
|
||||
processor.processKeyExchangeMessage(preKeyExchange);
|
||||
|
||||
IncomingPushMessage bundledMessage = message.withBody(preKeyExchange.getBundledMessage());
|
||||
IncomingPushMessage bundledMessage = message.withBody(preKeyExchange.getBundledMessage().serialize());
|
||||
handleReceivedSecureMessage(masterSecret, bundledMessage);
|
||||
} else {
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
|
@@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.textsecure.crypto.InvalidKeyException;
|
||||
import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||
import org.whispersystems.textsecure.storage.InvalidKeyIdException;
|
||||
|
||||
@@ -110,7 +111,8 @@ public class SmsReceiver {
|
||||
if (processor.isTrusted(preKeyExchange)) {
|
||||
processor.processKeyExchangeMessage(preKeyExchange);
|
||||
|
||||
String bundledMessageBody = new String(transportDetails.getEncodedMessage(preKeyExchange.getBundledMessage()));
|
||||
CiphertextMessage ciphertextMessage = preKeyExchange.getBundledMessage();
|
||||
String bundledMessageBody = new String(transportDetails.getEncodedMessage(ciphertextMessage.serialize()));
|
||||
IncomingEncryptedMessage bundledMessage = new IncomingEncryptedMessage(message, bundledMessageBody);
|
||||
Pair<Long, Long> messageAndThreadId = storeSecureMessage(masterSecret, bundledMessage);
|
||||
|
||||
|
@@ -18,9 +18,9 @@ package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.whispersystems.textsecure.crypto.SessionCipher;
|
||||
import org.whispersystems.textsecure.crypto.TransportDetails;
|
||||
import org.thoughtcrime.securesms.protocol.WirePrefix;
|
||||
import org.whispersystems.textsecure.crypto.TransportDetails;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -35,7 +35,7 @@ public class SmsTransportDetails implements TransportDetails {
|
||||
public static final int MULTI_MESSAGE_MAX_BYTES = BASE_MAX_BYTES - MultipartSmsTransportMessage.MULTI_MESSAGE_MULTIPART_OVERHEAD;
|
||||
public static final int FIRST_MULTI_MESSAGE_MAX_BYTES = BASE_MAX_BYTES - MultipartSmsTransportMessage.FIRST_MULTI_MESSAGE_MULTIPART_OVERHEAD;
|
||||
|
||||
public static final int ENCRYPTED_SINGLE_MESSAGE_BODY_MAX_SIZE = SINGLE_MESSAGE_MAX_BYTES - SessionCipher.ENCRYPTED_MESSAGE_OVERHEAD;
|
||||
public static final int ENCRYPTED_SINGLE_MESSAGE_BODY_MAX_SIZE = SINGLE_MESSAGE_MAX_BYTES - CiphertextMessage.ENCRYPTED_MESSAGE_OVERHEAD;
|
||||
|
||||
@Override
|
||||
public byte[] getEncodedMessage(byte[] messageWithMac) {
|
||||
@@ -73,7 +73,7 @@ public class SmsTransportDetails implements TransportDetails {
|
||||
@Override
|
||||
public byte[] getPaddedMessageBody(byte[] messageBody) {
|
||||
int paddedBodySize = getMaxBodySizeForBytes(messageBody.length);
|
||||
Log.w("SessionCipher", "Padding message body out to: " + paddedBodySize);
|
||||
Log.w("SmsTransportDetails", "Padding message body out to: " + paddedBodySize);
|
||||
|
||||
byte[] paddedBody = new byte[paddedBodySize];
|
||||
System.arraycopy(messageBody, 0, paddedBody, 0, messageBody.length);
|
||||
@@ -82,7 +82,7 @@ public class SmsTransportDetails implements TransportDetails {
|
||||
}
|
||||
|
||||
private int getMaxBodySizeForBytes(int bodyLength) {
|
||||
int encryptedBodyLength = bodyLength + SessionCipher.ENCRYPTED_MESSAGE_OVERHEAD;
|
||||
int encryptedBodyLength = bodyLength + CiphertextMessage.ENCRYPTED_MESSAGE_OVERHEAD;
|
||||
int messageRecordsForBody = getMessageCountForBytes(encryptedBodyLength);
|
||||
|
||||
if (messageRecordsForBody == 1) {
|
||||
@@ -91,7 +91,7 @@ public class SmsTransportDetails implements TransportDetails {
|
||||
return
|
||||
FIRST_MULTI_MESSAGE_MAX_BYTES +
|
||||
(MULTI_MESSAGE_MAX_BYTES * (messageRecordsForBody-1)) -
|
||||
SessionCipher.ENCRYPTED_MESSAGE_OVERHEAD;
|
||||
CiphertextMessage.ENCRYPTED_MESSAGE_OVERHEAD;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.mms.MmsSendHelper;
|
||||
import org.thoughtcrime.securesms.mms.TextTransport;
|
||||
import org.thoughtcrime.securesms.protocol.WirePrefix;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -134,10 +135,14 @@ public class MmsTransport {
|
||||
return encryptedPdu;
|
||||
}
|
||||
|
||||
private byte[] getEncryptedPdu(MasterSecret masterSecret, String recipient, byte[] pduBytes) {
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher message = new MessageCipher(context, masterSecret, identityKey, new TextTransport());
|
||||
return message.encrypt(new Recipient(null, recipient, null, null), pduBytes);
|
||||
private byte[] getEncryptedPdu(MasterSecret masterSecret, String recipientString, byte[] pduBytes) {
|
||||
TextTransport transportDetails = new TextTransport();
|
||||
Recipient recipient = new Recipient(null, recipientString, null, null);
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey);
|
||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, pduBytes);
|
||||
|
||||
return transportDetails.getEncodedMessage(ciphertextMessage.serialize());
|
||||
}
|
||||
|
||||
private boolean isInconsistentResponse(SendReq message, SendConf response) {
|
||||
|
@@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.transport;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.KeyExchangeProcessor;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
@@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePushCredentials;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.textsecure.crypto.AttachmentCipher;
|
||||
@@ -22,19 +21,17 @@ import org.whispersystems.textsecure.crypto.IdentityKeyPair;
|
||||
import org.whispersystems.textsecure.crypto.KeyUtil;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||
import org.whispersystems.textsecure.directory.Directory;
|
||||
import org.whispersystems.textsecure.push.OutgoingPushMessage;
|
||||
import org.whispersystems.textsecure.push.PreKeyEntity;
|
||||
import org.whispersystems.textsecure.push.PushAttachmentData;
|
||||
import org.whispersystems.textsecure.push.PushAttachmentPointer;
|
||||
import org.whispersystems.textsecure.push.PushBody;
|
||||
import org.whispersystems.textsecure.push.PushDestination;
|
||||
import org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent;
|
||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||
import org.whispersystems.textsecure.push.PushTransportDetails;
|
||||
import org.whispersystems.textsecure.push.RateLimitException;
|
||||
import org.whispersystems.textsecure.push.RawTransportDetails;
|
||||
import org.whispersystems.textsecure.util.PhoneNumberFormatter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
@@ -62,14 +59,11 @@ public class PushTransport extends BaseTransport {
|
||||
PushDestination destination = PushDestination.create(context, credentials,
|
||||
recipient.getNumber());
|
||||
|
||||
String plaintextBody = message.getBody().getBody();
|
||||
byte[] plaintext = PushMessageContent.newBuilder()
|
||||
.setBody(plaintextBody)
|
||||
.build().toByteArray();
|
||||
String plaintextBody = message.getBody().getBody();
|
||||
byte[] plaintext = PushMessageContent.newBuilder().setBody(plaintextBody).build().toByteArray();
|
||||
PushBody pushBody = getEncryptedMessage(socket, recipient, destination, plaintext);
|
||||
|
||||
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipient, destination, plaintext);
|
||||
|
||||
socket.sendMessage(destination, typeAndCiphertext.second, typeAndCiphertext.first);
|
||||
socket.sendMessage(destination, pushBody);
|
||||
|
||||
context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType()));
|
||||
} catch (RateLimitException e) {
|
||||
@@ -83,9 +77,7 @@ public class PushTransport extends BaseTransport {
|
||||
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
||||
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
||||
String messageBody = PartParser.getMessageText(message.getBody());
|
||||
|
||||
List<byte[]> ciphertext = new LinkedList<byte[]>();
|
||||
List<Integer> types = new LinkedList<Integer>();
|
||||
List<PushBody> pushBodies = new LinkedList<PushBody>();
|
||||
|
||||
for (PushDestination destination : destinations) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, destination.getNumber(), false);
|
||||
@@ -107,15 +99,13 @@ public class PushTransport extends BaseTransport {
|
||||
builder.addAttachments(attachmentBuilder.build());
|
||||
}
|
||||
|
||||
byte[] plaintext = builder.build().toByteArray();
|
||||
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipients.getPrimaryRecipient(),
|
||||
destination, plaintext);
|
||||
byte[] plaintext = builder.build().toByteArray();
|
||||
PushBody pushBody = getEncryptedMessage(socket, recipients.getPrimaryRecipient(), destination, plaintext);
|
||||
|
||||
types.add(typeAndCiphertext.first);
|
||||
ciphertext.add(typeAndCiphertext.second);
|
||||
pushBodies.add(pushBody);
|
||||
}
|
||||
|
||||
socket.sendMessage(destinations, ciphertext, types);
|
||||
socket.sendMessage(destinations, pushBodies);
|
||||
|
||||
} catch (RateLimitException e) {
|
||||
Log.w("PushTransport", e);
|
||||
@@ -150,37 +140,34 @@ public class PushTransport extends BaseTransport {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
private Pair<Integer, byte[]> getEncryptedMessage(PushServiceSocket socket,
|
||||
Recipient recipient,
|
||||
PushDestination pushDestination,
|
||||
byte[] plaintext)
|
||||
private PushBody getEncryptedMessage(PushServiceSocket socket, Recipient recipient,
|
||||
PushDestination pushDestination, byte[] plaintext)
|
||||
throws IOException
|
||||
{
|
||||
if (KeyUtil.isNonPrekeySessionFor(context, masterSecret, recipient)) {
|
||||
Log.w("PushTransport", "Sending standard ciphertext message...");
|
||||
byte[] ciphertext = getEncryptedMessageForExistingSession(recipient, plaintext);
|
||||
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_CIPHERTEXT, ciphertext);
|
||||
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_CIPHERTEXT, ciphertext);
|
||||
} else if (KeyUtil.isSessionFor(context, recipient)) {
|
||||
Log.w("PushTransport", "Sending prekeybundle ciphertext message for existing session...");
|
||||
byte[] ciphertext = getEncryptedPrekeyBundleMessageForExistingSession(recipient, plaintext);
|
||||
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||
} else {
|
||||
Log.w("PushTransport", "Sending prekeybundle ciphertext message for new session...");
|
||||
byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, recipient, pushDestination, plaintext);
|
||||
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||
return new PushBody(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getEncryptedPrekeyBundleMessageForExistingSession(Recipient recipient,
|
||||
byte[] plaintext)
|
||||
{
|
||||
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
IdentityKey identityKey = identityKeyPair.getPublicKey();
|
||||
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
IdentityKey identityKey = identityKeyPair.getPublicKey();
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKeyPair);
|
||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, plaintext);
|
||||
PreKeyBundleMessage preKeyBundleMessage = new PreKeyBundleMessage(ciphertextMessage, identityKey);
|
||||
|
||||
MessageCipher message = new MessageCipher(context, masterSecret, identityKeyPair, new RawTransportDetails());
|
||||
byte[] bundledMessage = message.encrypt(recipient, plaintext);
|
||||
|
||||
PreKeyBundleMessage preKeyBundleMessage = new PreKeyBundleMessage(identityKey, bundledMessage);
|
||||
return preKeyBundleMessage.serialize();
|
||||
}
|
||||
|
||||
@@ -197,21 +184,21 @@ public class PushTransport extends BaseTransport {
|
||||
|
||||
processor.processKeyExchangeMessage(preKey);
|
||||
|
||||
MessageCipher message = new MessageCipher(context, masterSecret, identityKeyPair, new RawTransportDetails());
|
||||
byte[] bundledMessage = message.encrypt(recipient, plaintext);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKeyPair);
|
||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, plaintext);
|
||||
PreKeyBundleMessage preKeyBundleMessage = new PreKeyBundleMessage(ciphertextMessage, identityKey);
|
||||
|
||||
PreKeyBundleMessage preKeyBundleMessage = new PreKeyBundleMessage(identityKey, bundledMessage);
|
||||
return preKeyBundleMessage.serialize();
|
||||
}
|
||||
|
||||
private byte[] getEncryptedMessageForExistingSession(Recipient recipient, byte[] plaintext)
|
||||
throws IOException
|
||||
{
|
||||
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKeyPair,
|
||||
new PushTransportDetails());
|
||||
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKeyPair);
|
||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, plaintext);
|
||||
|
||||
return messageCipher.encrypt(recipient, plaintext);
|
||||
return ciphertextMessage.serialize();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,21 +6,21 @@ import android.telephony.SmsManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingPrekeyBundleMessage;import org.whispersystems.textsecure.push.RawTransportDetails;
|
||||
import org.whispersystems.textsecure.crypto.IdentityKeyPair;
|
||||
import org.whispersystems.textsecure.crypto.KeyUtil;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.SendReceiveService;
|
||||
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
||||
import org.thoughtcrime.securesms.sms.MultipartSmsMessageHandler;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingPrekeyBundleMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.sms.SmsTransportDetails;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.textsecure.crypto.IdentityKeyPair;
|
||||
import org.whispersystems.textsecure.crypto.KeyUtil;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||
import org.whispersystems.textsecure.crypto.protocol.CiphertextMessage;
|
||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||
import org.whispersystems.textsecure.util.Base64;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -144,23 +144,28 @@ public class SmsTransport extends BaseTransport {
|
||||
private OutgoingTextMessage getAsymmetricEncrypt(MasterSecret masterSecret,
|
||||
OutgoingTextMessage message)
|
||||
{
|
||||
Recipient recipient = message.getRecipients().getPrimaryRecipient();
|
||||
String body = message.getMessageBody();
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
Recipient recipient = message.getRecipients().getPrimaryRecipient();
|
||||
String body = message.getMessageBody();
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||
SmsTransportDetails transportDetails = new SmsTransportDetails();
|
||||
|
||||
if (KeyUtil.isNonPrekeySessionFor(context, masterSecret, recipient)) {
|
||||
Log.w("SmsTransport", "Delivering standard ciphertext...");
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey, new SmsTransportDetails());
|
||||
byte[] ciphertext = messageCipher.encrypt(recipient, body.getBytes());
|
||||
|
||||
return message.withBody(new String(ciphertext));
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey);
|
||||
byte[] paddedPlaintext = transportDetails.getPaddedMessageBody(body.getBytes());
|
||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, paddedPlaintext);
|
||||
String ciphertxt = new String(transportDetails.getEncodedMessage(ciphertextMessage.serialize()));
|
||||
|
||||
return message.withBody(ciphertxt);
|
||||
} else {
|
||||
Log.w("SmsTransport", "Delivering prekeybundle ciphertext...");
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey, new RawTransportDetails());
|
||||
byte[] bundledMessage = messageCipher.encrypt(recipient, body.getBytes());
|
||||
PreKeyBundleMessage preKeyBundleMessage = new PreKeyBundleMessage(identityKey.getPublicKey(), bundledMessage);
|
||||
MessageCipher messageCipher = new MessageCipher(context, masterSecret, identityKey);
|
||||
CiphertextMessage ciphertextMessage = messageCipher.encrypt(recipient, body.getBytes());
|
||||
PreKeyBundleMessage preKeyBundleMessage = new PreKeyBundleMessage(ciphertextMessage, identityKey.getPublicKey());
|
||||
byte[] cipherText = preKeyBundleMessage.serialize();
|
||||
|
||||
return new OutgoingPrekeyBundleMessage(message, Base64.encodeBytesWithoutPadding(preKeyBundleMessage.serialize()));
|
||||
return new OutgoingPrekeyBundleMessage(message, new String(transportDetails.getEncodedMessage(cipherText)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user