mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-30 13:35:18 +00:00
feat: upgrade to keystore sealed identity key preferences
This commit is contained in:
parent
3bf5a50439
commit
91aefb7c87
@ -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;
|
||||
@ -155,7 +159,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
MessagingModuleConfiguration.Companion.configure(this,
|
||||
DatabaseFactory.getStorage(this),
|
||||
DatabaseFactory.getAttachmentProvider(this));
|
||||
DatabaseFactory.getAttachmentProvider(this),
|
||||
()-> KeyPairUtilities.INSTANCE.getUserED25519KeyPair(this)
|
||||
);
|
||||
SnodeModule.Companion.configure(apiDB, broadcaster);
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey != null) {
|
||||
|
@ -15,21 +15,22 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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();
|
||||
|
||||
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");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.session.libsession.utilities
|
||||
package org.thoughtcrime.securesms.crypto
|
||||
|
||||
import android.content.Context
|
||||
import com.goterl.lazysodium.LazySodiumAndroid
|
@ -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
|
||||
|
@ -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?) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.*
|
||||
|
@ -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() {
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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() {
|
||||
|
||||
|
@ -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() {
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,13 +1,15 @@
|
||||
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 {
|
||||
@ -15,10 +17,11 @@ class MessagingModuleConfiguration(
|
||||
|
||||
fun configure(context: Context,
|
||||
storage: StorageProtocol,
|
||||
messageDataProvider: MessageDataProvider
|
||||
messageDataProvider: MessageDataProvider,
|
||||
keyPairProvider: () -> KeyPair?
|
||||
) {
|
||||
if (Companion::shared.isInitialized) { return }
|
||||
shared = MessagingModuleConfiguration(context, storage, messageDataProvider)
|
||||
shared = MessagingModuleConfiguration(context, storage, messageDataProvider, keyPairProvider)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user