From 91aefb7c87161475f841882877b1de2644893c84 Mon Sep 17 00:00:00 2001 From: Harris Date: Mon, 7 Jun 2021 11:53:17 +1000 Subject: [PATCH 1/7] feat: upgrade to keystore sealed identity key preferences --- .../securesms/ApplicationContext.java | 10 +++- .../securesms/crypto}/IdentityKeyUtil.java | 57 ++++++++++++++++--- .../securesms/crypto}/KeyPairUtilities.kt | 2 +- .../securesms/database/Storage.kt | 2 +- .../loki/activities/LandingActivity.kt | 5 +- .../loki/activities/LinkDeviceActivity.kt | 6 +- .../RecoveryPhraseRestoreActivity.kt | 6 +- .../loki/activities/RegisterActivity.kt | 2 +- .../securesms/loki/activities/SeedActivity.kt | 8 +-- .../loki/database/LokiAPIDatabase.kt | 17 +++--- .../loki/dialogs/ClearAllDataDialog.kt | 6 +- .../securesms/loki/dialogs/SeedDialog.kt | 4 +- .../thoughtcrime/securesms/util/BackupUtil.kt | 2 +- .../messaging/MessagingModuleConfiguration.kt | 11 ++-- .../sending_receiving/MessageEncrypter.kt | 3 +- 15 files changed, 96 insertions(+), 45 deletions(-) rename {libsession/src/main/java/org/session/libsession/utilities => app/src/main/java/org/thoughtcrime/securesms/crypto}/IdentityKeyUtil.java (68%) rename {libsession/src/main/java/org/session/libsession/utilities => app/src/main/java/org/thoughtcrime/securesms/crypto}/KeyPairUtilities.kt (98%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 0eacf377a5..2d8ff78129 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -27,6 +27,7 @@ import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ProcessLifecycleOwner; import androidx.multidex.MultiDexApplication; + import org.conscrypt.Conscrypt; import org.session.libsession.avatars.AvatarHelper; import org.session.libsession.messaging.MessagingModuleConfiguration; @@ -47,6 +48,7 @@ import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.ThreadUtils; import org.signal.aesgcmprovider.AesGcmProvider; import org.thoughtcrime.securesms.components.TypingStatusSender; +import org.thoughtcrime.securesms.crypto.KeyPairUtilities; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule; @@ -84,12 +86,14 @@ import org.webrtc.PeerConnectionFactory; import org.webrtc.PeerConnectionFactory.InitializationOptions; import org.webrtc.voiceengine.WebRtcAudioManager; import org.webrtc.voiceengine.WebRtcAudioUtils; + import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.security.Security; import java.util.Date; import java.util.HashSet; import java.util.Set; + import dagger.ObjectGraph; import kotlin.Unit; import kotlinx.coroutines.Job; @@ -154,8 +158,10 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc conversationListNotificationHandler = new Handler(Looper.getMainLooper()); LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this); MessagingModuleConfiguration.Companion.configure(this, - DatabaseFactory.getStorage(this), - DatabaseFactory.getAttachmentProvider(this)); + DatabaseFactory.getStorage(this), + DatabaseFactory.getAttachmentProvider(this), + ()-> KeyPairUtilities.INSTANCE.getUserED25519KeyPair(this) + ); SnodeModule.Companion.configure(apiDB, broadcaster); String userPublicKey = TextSecurePreferences.getLocalNumber(this); if (userPublicKey != null) { diff --git a/libsession/src/main/java/org/session/libsession/utilities/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java similarity index 68% rename from libsession/src/main/java/org/session/libsession/utilities/IdentityKeyUtil.java rename to app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index d42f5c2ac5..4d48896817 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -15,21 +15,22 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.session.libsession.utilities; +package org.thoughtcrime.securesms.crypto; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.os.Build; + import androidx.annotation.NonNull; -import org.session.libsignal.crypto.ecc.ECPublicKey; import org.session.libsignal.crypto.IdentityKey; import org.session.libsignal.crypto.IdentityKeyPair; -import org.session.libsignal.exceptions.InvalidKeyException; import org.session.libsignal.crypto.ecc.Curve; import org.session.libsignal.crypto.ecc.ECKeyPair; import org.session.libsignal.crypto.ecc.ECPrivateKey; - +import org.session.libsignal.crypto.ecc.ECPublicKey; +import org.session.libsignal.exceptions.InvalidKeyException; import org.session.libsignal.utilities.Base64; import java.io.IOException; @@ -45,6 +46,7 @@ public class IdentityKeyUtil { @SuppressWarnings("unused") private static final String TAG = IdentityKeyUtil.class.getSimpleName(); + private static final String ENCRYPTED_SUFFIX = "_encrypted"; public static final String IDENTITY_PUBLIC_KEY_PREF = "pref_identity_public_v3"; public static final String IDENTITY_PRIVATE_KEY_PREF = "pref_identity_private_v3"; @@ -56,8 +58,10 @@ public class IdentityKeyUtil { SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); return - preferences.contains(IDENTITY_PUBLIC_KEY_PREF) && - preferences.contains(IDENTITY_PRIVATE_KEY_PREF); + (preferences.contains(IDENTITY_PUBLIC_KEY_PREF) && + preferences.contains(IDENTITY_PRIVATE_KEY_PREF)) + || (preferences.contains(IDENTITY_PUBLIC_KEY_PREF+ENCRYPTED_SUFFIX) && + preferences.contains(IDENTITY_PRIVATE_KEY_PREF+ENCRYPTED_SUFFIX)); } public static @NonNull IdentityKey getIdentityKey(@NonNull Context context) { @@ -94,14 +98,51 @@ public class IdentityKeyUtil { public static String retrieve(Context context, String key) { SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); - return preferences.getString(key, null); + + String unencryptedSecret = preferences.getString(key, null); + String encryptedSecret = preferences.getString(key+ENCRYPTED_SUFFIX, null); + + if (unencryptedSecret != null) return getUnencryptedSecret(key, unencryptedSecret, context); + else if (encryptedSecret != null) return getEncryptedSecret(encryptedSecret); + + return null; } + private static String getUnencryptedSecret(String key, String unencryptedSecret, Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return unencryptedSecret; + } else { + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes()); + + // save the encrypted suffix secret "key_encrypted" + save(context,key+ENCRYPTED_SUFFIX,encryptedSecret.serialize()); + // delete the regular secret "key" + delete(context,key); + + return unencryptedSecret; + } + } + + private static String getEncryptedSecret(String encryptedSecret) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!"); + } else { + KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret); + return new String(KeyStoreHelper.unseal(sealedData)); + } + } + + public static void save(Context context, String key, String value) { SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); Editor preferencesEditor = preferences.edit(); - preferencesEditor.putString(key, value); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); + preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); + } else { + preferencesEditor.putString(key, value); + } if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences"); } diff --git a/libsession/src/main/java/org/session/libsession/utilities/KeyPairUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyPairUtilities.kt similarity index 98% rename from libsession/src/main/java/org/session/libsession/utilities/KeyPairUtilities.kt rename to app/src/main/java/org/thoughtcrime/securesms/crypto/KeyPairUtilities.kt index dfefaa2f12..652732f081 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/KeyPairUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyPairUtilities.kt @@ -1,4 +1,4 @@ -package org.session.libsession.utilities +package org.thoughtcrime.securesms.crypto import android.content.Context import com.goterl.lazysodium.LazySodiumAndroid diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 66b4fd5004..2f6405dc9b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -1,6 +1,5 @@ package org.thoughtcrime.securesms.database -import android.app.job.JobScheduler import android.content.Context import android.net.Uri import org.session.libsession.database.StorageProtocol @@ -27,6 +26,7 @@ import org.session.libsignal.messages.SignalServiceGroup import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.guava.Optional import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob import org.thoughtcrime.securesms.loki.api.OpenGroupManager diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LandingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LandingActivity.kt index 50080956ba..3388915609 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LandingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LandingActivity.kt @@ -4,16 +4,15 @@ import android.content.Intent import android.os.Bundle import android.view.View import network.loki.messenger.R +import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.BaseActionBarActivity -import org.session.libsession.utilities.IdentityKeyUtil +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo import org.thoughtcrime.securesms.loki.views.FakeChatView import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.util.Util -import org.session.libsession.utilities.TextSecurePreferences - class LandingActivity : BaseActionBarActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt index 20f8fcf795..5f04b2b34e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt @@ -23,16 +23,16 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.crypto.MnemonicCodec -import org.session.libsignal.utilities.hexEncodedPublicKey import org.session.libsignal.utilities.Hex +import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.Log +import org.session.libsignal.utilities.hexEncodedPublicKey import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.BaseActionBarActivity +import org.thoughtcrime.securesms.crypto.KeyPairUtilities import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragmentDelegate -import org.session.libsession.utilities.KeyPairUtilities import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt index c3e01217d9..f4dc7b323c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt @@ -14,12 +14,12 @@ import android.widget.Toast import kotlinx.android.synthetic.main.activity_recovery_phrase_restore.* import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.crypto.MnemonicCodec -import org.session.libsignal.utilities.hexEncodedPublicKey import org.session.libsignal.utilities.Hex +import org.session.libsignal.utilities.KeyHelper +import org.session.libsignal.utilities.hexEncodedPublicKey import org.thoughtcrime.securesms.BaseActionBarActivity -import org.session.libsession.utilities.KeyPairUtilities +import org.thoughtcrime.securesms.crypto.KeyPairUtilities import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt index c9e5bd83cc..27ab501a68 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt @@ -18,12 +18,12 @@ import android.widget.Toast import com.goterl.lazysodium.utils.KeyPair import kotlinx.android.synthetic.main.activity_register.* import network.loki.messenger.R -import org.session.libsession.utilities.KeyPairUtilities import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.crypto.ecc.ECKeyPair import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.hexEncodedPublicKey import org.thoughtcrime.securesms.BaseActionBarActivity +import org.thoughtcrime.securesms.crypto.KeyPairUtilities import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo import java.util.* diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt index a7f10da4a8..aed826e086 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt @@ -11,13 +11,13 @@ import android.widget.LinearLayout import android.widget.Toast import kotlinx.android.synthetic.main.activity_seed.* import network.loki.messenger.R -import org.thoughtcrime.securesms.BaseActionBarActivity -import org.session.libsession.utilities.IdentityKeyUtil -import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities -import org.thoughtcrime.securesms.loki.utilities.getColorWithID import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.crypto.MnemonicCodec import org.session.libsignal.utilities.hexEncodedPrivateKey +import org.thoughtcrime.securesms.BaseActionBarActivity +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil +import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities +import org.thoughtcrime.securesms.loki.utilities.getColorWithID class SeedActivity : BaseActionBarActivity() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt index 91f04adef8..f9bfe7f862 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt @@ -2,22 +2,25 @@ package org.thoughtcrime.securesms.loki.database import android.content.ContentValues import android.content.Context -import org.session.libsession.utilities.IdentityKeyUtil import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.crypto.ecc.DjbECPrivateKey import org.session.libsignal.crypto.ecc.DjbECPublicKey import org.session.libsignal.crypto.ecc.ECKeyPair -import org.session.libsignal.utilities.Snode import org.session.libsignal.database.LokiAPIDatabaseProtocol -import org.session.libsignal.utilities.PublicKeyValidation -import org.session.libsignal.utilities.removing05PrefixIfNeeded -import org.session.libsignal.utilities.toHexString -import org.session.libsignal.utilities.Hex -import org.session.libsignal.utilities.Log +import org.session.libsignal.utilities.* +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.Database import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.loki.utilities.* import java.util.* +import kotlin.Array +import kotlin.Boolean +import kotlin.Int +import kotlin.Long +import kotlin.Pair +import kotlin.String +import kotlin.arrayOf +import kotlin.to class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiAPIDatabaseProtocol { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt index cb1bf22566..7e98a8a949 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/ClearAllDataDialog.kt @@ -4,14 +4,14 @@ import android.app.Dialog import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.os.Bundle -import androidx.fragment.app.DialogFragment -import androidx.appcompat.app.AlertDialog import android.view.LayoutInflater +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment import kotlinx.android.synthetic.main.dialog_clear_all_data.view.* import network.loki.messenger.R import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.crypto.KeyPairUtilities import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol -import org.session.libsession.utilities.KeyPairUtilities class ClearAllDataDialog : DialogFragment() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt index 2bd9595b22..eceb36c146 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt @@ -13,10 +13,10 @@ import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import kotlinx.android.synthetic.main.dialog_seed.view.* import network.loki.messenger.R -import org.session.libsession.utilities.IdentityKeyUtil -import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities import org.session.libsignal.crypto.MnemonicCodec import org.session.libsignal.utilities.hexEncodedPrivateKey +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil +import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities class SeedDialog : DialogFragment() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt index b597835e05..e38df7391b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt @@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.backup.BackupPassphrase import org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference import org.thoughtcrime.securesms.backup.FullBackupExporter import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider -import org.session.libsession.utilities.IdentityKeyUtil +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.loki.database.BackupFileRecord import org.thoughtcrime.securesms.service.LocalBackupListener diff --git a/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt b/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt index f6e4445dde..f887a8f383 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt @@ -1,24 +1,27 @@ package org.session.libsession.messaging import android.content.Context +import com.goterl.lazysodium.utils.KeyPair import org.session.libsession.database.MessageDataProvider import org.session.libsession.database.StorageProtocol class MessagingModuleConfiguration( val context: Context, val storage: StorageProtocol, - val messageDataProvider: MessageDataProvider + val messageDataProvider: MessageDataProvider, + val keyPairProvider: ()-> KeyPair? ) { companion object { lateinit var shared: MessagingModuleConfiguration fun configure(context: Context, - storage: StorageProtocol, - messageDataProvider: MessageDataProvider + storage: StorageProtocol, + messageDataProvider: MessageDataProvider, + keyPairProvider: () -> KeyPair? ) { if (Companion::shared.isInitialized) { return } - shared = MessagingModuleConfiguration(context, storage, messageDataProvider) + shared = MessagingModuleConfiguration(context, storage, messageDataProvider, keyPairProvider) } } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt index ef91eae598..cbd97e12f7 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt @@ -6,7 +6,6 @@ import com.goterl.lazysodium.interfaces.Box import com.goterl.lazysodium.interfaces.Sign import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.sending_receiving.MessageSender.Error -import org.session.libsession.utilities.KeyPairUtilities import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.removing05PrefixIfNeeded @@ -25,7 +24,7 @@ object MessageEncrypter { */ internal fun encrypt(plaintext: ByteArray, recipientHexEncodedX25519PublicKey: String): ByteArray{ val context = MessagingModuleConfiguration.shared.context - val userED25519KeyPair = KeyPairUtilities.getUserED25519KeyPair(context) ?: throw Error.NoUserED25519KeyPair + val userED25519KeyPair = MessagingModuleConfiguration.shared.keyPairProvider() ?: throw Error.NoUserED25519KeyPair val recipientX25519PublicKey = Hex.fromStringCondensed(recipientHexEncodedX25519PublicKey.removing05PrefixIfNeeded()) val verificationData = plaintext + userED25519KeyPair.publicKey.asBytes + recipientX25519PublicKey From 596b02cfaf363a4c8682958b3118bf7e76c11f14 Mon Sep 17 00:00:00 2001 From: Harris Date: Mon, 7 Jun 2021 12:00:21 +1000 Subject: [PATCH 2/7] fix: don't double encrypt on save --- .../org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index 4d48896817..c48f900f3f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -139,7 +139,12 @@ public class IdentityKeyUtil { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); - preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); + boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX); + if (isEncryptedSuffix) { + preferencesEditor.putString(key, encryptedSecret.serialize()); + } else { + preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); + } } else { preferencesEditor.putString(key, value); } From f10a99ce41a4a7abf4322e2c649c15c1f5e257ee Mon Sep 17 00:00:00 2001 From: Harris Date: Mon, 7 Jun 2021 15:23:20 +1000 Subject: [PATCH 3/7] fix: don't put encrypted in encrypted --- .../org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index c48f900f3f..356a8a6fd1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -138,11 +138,11 @@ public class IdentityKeyUtil { Editor preferencesEditor = preferences.edit(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX); if (isEncryptedSuffix) { - preferencesEditor.putString(key, encryptedSecret.serialize()); + preferencesEditor.putString(key, value); } else { + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); } } else { From 11b44a5ddea2bd5262f6a54ef55dcc8dc73b132c Mon Sep 17 00:00:00 2001 From: Harris Date: Wed, 9 Jun 2021 10:35:24 +1000 Subject: [PATCH 4/7] feat: force upgrade on check if identity key exists --- .../securesms/crypto/IdentityKeyUtil.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index 356a8a6fd1..c3ed88e896 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -57,11 +57,26 @@ public class IdentityKeyUtil { public static boolean hasIdentityKey(Context context) { SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); - return - (preferences.contains(IDENTITY_PUBLIC_KEY_PREF) && - preferences.contains(IDENTITY_PRIVATE_KEY_PREF)) + boolean hasIdentityKey = (preferences.contains(IDENTITY_PUBLIC_KEY_PREF) && + preferences.contains(IDENTITY_PRIVATE_KEY_PREF)) || (preferences.contains(IDENTITY_PUBLIC_KEY_PREF+ENCRYPTED_SUFFIX) && - preferences.contains(IDENTITY_PRIVATE_KEY_PREF+ENCRYPTED_SUFFIX)); + preferences.contains(IDENTITY_PRIVATE_KEY_PREF+ENCRYPTED_SUFFIX)); + + // check if any keys are not migrated + if (hasIdentityKey) { + checkUpdate(context); + } + + return hasIdentityKey; + } + + private static void checkUpdate(Context context) { + // retrieve will force upgrade if available + retrieve(context,IDENTITY_PUBLIC_KEY_PREF); + retrieve(context,IDENTITY_PRIVATE_KEY_PREF); + retrieve(context,ED25519_PUBLIC_KEY); + retrieve(context,ED25519_SECRET_KEY); + retrieve(context,LOKI_SEED); } public static @NonNull IdentityKey getIdentityKey(@NonNull Context context) { From 645bf66424424e8608d8affc12dc5262bb08d5a2 Mon Sep 17 00:00:00 2001 From: Harris Date: Wed, 9 Jun 2021 11:31:45 +1000 Subject: [PATCH 5/7] feat: only FORCE upgrade if not upgraded yet --- .../org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index c3ed88e896..2ca215c894 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -53,6 +53,7 @@ public class IdentityKeyUtil { public static final String ED25519_PUBLIC_KEY = "pref_ed25519_public_key"; public static final String ED25519_SECRET_KEY = "pref_ed25519_secret_key"; public static final String LOKI_SEED = "loki_seed"; + public static final String HAS_MIGRATED_KEY = "has_migrated_keys"; public static boolean hasIdentityKey(Context context) { SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); @@ -63,8 +64,10 @@ public class IdentityKeyUtil { preferences.contains(IDENTITY_PRIVATE_KEY_PREF+ENCRYPTED_SUFFIX)); // check if any keys are not migrated - if (hasIdentityKey) { + if (hasIdentityKey && !preferences.getBoolean(HAS_MIGRATED_KEY, false)) { + // this will retrieve and force upgrade if possible checkUpdate(context); + preferences.edit().putBoolean(HAS_MIGRATED_KEY, true).apply(); } return hasIdentityKey; From 3c1b0ff1e1b6cf38cd6df3f1c2cba01a01085c0a Mon Sep 17 00:00:00 2001 From: Harris Date: Wed, 9 Jun 2021 15:56:20 +1000 Subject: [PATCH 6/7] feat: extract upgrade to HomeActivity.kt resume instead of access --- .../securesms/crypto/IdentityKeyUtil.java | 39 ++++++++++--------- .../securesms/loki/activities/HomeActivity.kt | 9 ++--- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index 2ca215c894..a5333ef5d4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -55,31 +55,32 @@ public class IdentityKeyUtil { public static final String LOKI_SEED = "loki_seed"; public static final String HAS_MIGRATED_KEY = "has_migrated_keys"; - public static boolean hasIdentityKey(Context context) { - SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); + private static SharedPreferences getSharedPreferences(Context context) { + return context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); + } - boolean hasIdentityKey = (preferences.contains(IDENTITY_PUBLIC_KEY_PREF) && + public static boolean hasIdentityKey(Context context) { + SharedPreferences preferences = getSharedPreferences(context); + + return (preferences.contains(IDENTITY_PUBLIC_KEY_PREF) && preferences.contains(IDENTITY_PRIVATE_KEY_PREF)) || (preferences.contains(IDENTITY_PUBLIC_KEY_PREF+ENCRYPTED_SUFFIX) && preferences.contains(IDENTITY_PRIVATE_KEY_PREF+ENCRYPTED_SUFFIX)); - - // check if any keys are not migrated - if (hasIdentityKey && !preferences.getBoolean(HAS_MIGRATED_KEY, false)) { - // this will retrieve and force upgrade if possible - checkUpdate(context); - preferences.edit().putBoolean(HAS_MIGRATED_KEY, true).apply(); - } - - return hasIdentityKey; } - private static void checkUpdate(Context context) { - // retrieve will force upgrade if available - retrieve(context,IDENTITY_PUBLIC_KEY_PREF); - retrieve(context,IDENTITY_PRIVATE_KEY_PREF); - retrieve(context,ED25519_PUBLIC_KEY); - retrieve(context,ED25519_SECRET_KEY); - retrieve(context,LOKI_SEED); + public static void checkUpdate(Context context) { + SharedPreferences preferences = getSharedPreferences(context); + // check if any keys are not migrated + if (hasIdentityKey(context) && !preferences.getBoolean(HAS_MIGRATED_KEY, false)) { + // this will retrieve and force upgrade if possible + // retrieve will force upgrade if available + retrieve(context,IDENTITY_PUBLIC_KEY_PREF); + retrieve(context,IDENTITY_PRIVATE_KEY_PREF); + retrieve(context,ED25519_PUBLIC_KEY); + retrieve(context,ED25519_SECRET_KEY); + retrieve(context,LOKI_SEED); + preferences.edit().putBoolean(HAS_MIGRATED_KEY, true).apply(); + } } public static @NonNull IdentityKey getIdentityKey(@NonNull Context context) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt index 54cf2f8d7c..f65b00538d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt @@ -29,15 +29,14 @@ import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.session.libsession.messaging.jobs.JobQueue -import org.session.libsession.messaging.mentions.MentionsManager import org.session.libsession.messaging.sending_receiving.MessageSender -import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPollerV2 import org.session.libsession.utilities.* -import org.session.libsignal.utilities.toHexString import org.session.libsignal.utilities.ThreadUtils +import org.session.libsignal.utilities.toHexString import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.conversation.ConversationActivity +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.ThreadRecord import org.thoughtcrime.securesms.loki.api.OpenGroupManager @@ -155,8 +154,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis override fun onResume() { super.onResume() - if (TextSecurePreferences.getLocalNumber(this) == null) { - return; } // This can be the case after a secondary device is auto-cleared + if (TextSecurePreferences.getLocalNumber(this) == null) { return; } // This can be the case after a secondary device is auto-cleared + IdentityKeyUtil.checkUpdate(this) profileButton.recycle() // clear cached image before update tje profilePictureView profileButton.update() val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this) From a716b3dd4020f4ee8068ed42c2a6c853c651dae4 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Thu, 8 Jul 2021 10:55:08 +1000 Subject: [PATCH 7/7] Update version number --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d86c8a3a02..2d80c653b9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -143,8 +143,8 @@ dependencies { testImplementation 'org.robolectric:shadows-multidex:4.2' } -def canonicalVersionCode = 193 -def canonicalVersionName = "1.11.2" +def canonicalVersionCode = 194 +def canonicalVersionName = "1.11.3" def postFixSize = 10 def abiPostFix = ['armeabi-v7a' : 1,