mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 20:15:21 +00:00
Update for seed changes
This commit is contained in:
parent
24a03cd5bc
commit
ae54c641a9
@ -465,7 +465,7 @@
|
|||||||
android:windowSoftInputMode="stateUnchanged"
|
android:windowSoftInputMode="stateUnchanged"
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||||
|
|
||||||
<activity android:name="org.thoughtcrime.securesms.loki.KeyPairActivity"
|
<activity android:name="org.thoughtcrime.securesms.loki.SeedActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/TextSecure.DarkRegistrationTheme"
|
android:theme="@style/TextSecure.DarkRegistrationTheme"
|
||||||
android:windowSoftInputMode="stateUnchanged"
|
android:windowSoftInputMode="stateUnchanged"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".loki.KeyPairActivity">
|
tools:context=".loki.SeedActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
@ -311,8 +311,12 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
break;
|
break;
|
||||||
case PREFERENCE_CATEGORY_SEED:
|
case PREFERENCE_CATEGORY_SEED:
|
||||||
File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir);
|
File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir);
|
||||||
String hexEncodedPrivateKey = SerializationKt.getHexEncodedPrivateKey(IdentityKeyUtil.getIdentityKeyPair(getContext()));
|
try {
|
||||||
String seed = new MnemonicCodec(languageFileDirectory).encode(hexEncodedPrivateKey, MnemonicCodec.Language.Configuration.Companion.getEnglish());
|
String hexEncodedSeed = IdentityKeyUtil.retrieve(getContext(), IdentityKeyUtil.lokiSeedKey);
|
||||||
|
if (hexEncodedSeed == null) {
|
||||||
|
hexEncodedSeed = SerializationKt.getHexEncodedPrivateKey(IdentityKeyUtil.getIdentityKeyPair(getContext())); // Legacy account
|
||||||
|
}
|
||||||
|
String seed = new MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed, MnemonicCodec.Language.Configuration.Companion.getEnglish());
|
||||||
new AlertDialog.Builder(getContext())
|
new AlertDialog.Builder(getContext())
|
||||||
.setTitle(R.string.activity_settings_seed_dialog_title)
|
.setTitle(R.string.activity_settings_seed_dialog_title)
|
||||||
.setMessage(seed)
|
.setMessage(seed)
|
||||||
@ -324,6 +328,9 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
})
|
})
|
||||||
.setNeutralButton(R.string.activity_settings_seed_dialog_ok_button_title, null)
|
.setNeutralButton(R.string.activity_settings_seed_dialog_ok_button_title, null)
|
||||||
.show();
|
.show();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
|
@ -65,7 +65,7 @@ public class PassphraseCreateActivity extends PassphraseActivity {
|
|||||||
passphrase);
|
passphrase);
|
||||||
|
|
||||||
MasterSecretUtil.generateAsymmetricMasterSecret(PassphraseCreateActivity.this, masterSecret);
|
MasterSecretUtil.generateAsymmetricMasterSecret(PassphraseCreateActivity.this, masterSecret);
|
||||||
IdentityKeyUtil.generateIdentityKeys(PassphraseCreateActivity.this);
|
IdentityKeyUtil.generateIdentityKeyPair(PassphraseCreateActivity.this);
|
||||||
VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this);
|
VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this);
|
||||||
|
|
||||||
TextSecurePreferences.setLastExperienceVersionCode(PassphraseCreateActivity.this, Util.getCanonicalVersionCode());
|
TextSecurePreferences.setLastExperienceVersionCode(PassphraseCreateActivity.this, Util.getCanonicalVersionCode());
|
||||||
|
@ -24,14 +24,12 @@ import android.support.annotation.NonNull;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.backup.BackupProtos;
|
import org.thoughtcrime.securesms.backup.BackupProtos;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
import org.thoughtcrime.securesms.util.Hex;
|
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.ecc.Curve;
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
import org.whispersystems.libsignal.ecc.ECKeyPair;
|
import org.whispersystems.libsignal.ecc.ECKeyPair;
|
||||||
import org.whispersystems.libsignal.ecc.ECPrivateKey;
|
import org.whispersystems.libsignal.ecc.ECPrivateKey;
|
||||||
import org.whispersystems.libsignal.logging.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -54,6 +52,8 @@ public class IdentityKeyUtil {
|
|||||||
private static final String IDENTITY_PUBLIC_KEY_PREF = "pref_identity_public_v3";
|
private static final String IDENTITY_PUBLIC_KEY_PREF = "pref_identity_public_v3";
|
||||||
private static final String IDENTITY_PRIVATE_KEY_PREF = "pref_identity_private_v3";
|
private static final String IDENTITY_PRIVATE_KEY_PREF = "pref_identity_private_v3";
|
||||||
|
|
||||||
|
public static final String lokiSeedKey = "loki_seed";
|
||||||
|
|
||||||
public static boolean hasIdentityKey(Context context) {
|
public static boolean hasIdentityKey(Context context) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
||||||
|
|
||||||
@ -86,25 +86,21 @@ public class IdentityKeyUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateIdentityKeyPair(Context context, String hexEncodedPrivateKey) {
|
public static void generateIdentityKeyPair(Context context, byte[] seed) {
|
||||||
try {
|
ECKeyPair keyPair;
|
||||||
byte[] privateKey = Hex.fromStringCondensed(hexEncodedPrivateKey);
|
if (seed != null) {
|
||||||
ECKeyPair keyPair = Curve.generateKeyPair(privateKey);
|
keyPair = Curve.generateKeyPair(seed);
|
||||||
|
} else {
|
||||||
|
keyPair = Curve.generateKeyPair();
|
||||||
|
}
|
||||||
IdentityKey publicKey = new IdentityKey(keyPair.getPublicKey());
|
IdentityKey publicKey = new IdentityKey(keyPair.getPublicKey());
|
||||||
|
ECPrivateKey privateKey = keyPair.getPrivateKey();
|
||||||
save(context, IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(publicKey.serialize()));
|
save(context, IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(publicKey.serialize()));
|
||||||
save(context, IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair.getPrivateKey().serialize()));
|
save(context, IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(privateKey.serialize()));
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d("Loki", "Couldn't restore key pair from seed due to error: " + e.getMessage() + ".");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateIdentityKeys(Context context) {
|
public static void generateIdentityKeyPair(Context context) {
|
||||||
ECKeyPair djbKeyPair = Curve.generateKeyPair();
|
generateIdentityKeyPair(context, null);
|
||||||
IdentityKey djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey());
|
|
||||||
ECPrivateKey djbPrivateKey = djbKeyPair.getPrivateKey();
|
|
||||||
|
|
||||||
save(context, IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(djbIdentityKey.serialize()));
|
|
||||||
save(context, IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(djbPrivateKey.serialize()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void migrateIdentityKeys(@NonNull Context context,
|
public static void migrateIdentityKeys(@NonNull Context context,
|
||||||
@ -120,7 +116,7 @@ public class IdentityKeyUtil {
|
|||||||
delete(context, IDENTITY_PUBLIC_KEY_CIPHERTEXT_LEGACY_PREF);
|
delete(context, IDENTITY_PUBLIC_KEY_CIPHERTEXT_LEGACY_PREF);
|
||||||
delete(context, IDENTITY_PRIVATE_KEY_CIPHERTEXT_LEGACY_PREF);
|
delete(context, IDENTITY_PRIVATE_KEY_CIPHERTEXT_LEGACY_PREF);
|
||||||
} else {
|
} else {
|
||||||
generateIdentityKeys(context);
|
generateIdentityKeyPair(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,12 +159,12 @@ public class IdentityKeyUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String retrieve(Context context, String key) {
|
public static String retrieve(Context context, String key) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
||||||
return preferences.getString(key, null);
|
return preferences.getString(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void save(Context context, String key, String value) {
|
public static void save(Context context, String key, String value) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
||||||
Editor preferencesEditor = preferences.edit();
|
Editor preferencesEditor = preferences.edit();
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class AccountDetailsActivity : BaseActionBarActivity() {
|
|||||||
}
|
}
|
||||||
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
inputMethodManager.hideSoftInputFromWindow(nameEditText.windowToken, 0)
|
inputMethodManager.hideSoftInputFromWindow(nameEditText.windowToken, 0)
|
||||||
startActivity(Intent(this, KeyPairActivity::class.java))
|
startActivity(Intent(this, SeedActivity::class.java))
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,8 +8,8 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import kotlinx.android.synthetic.main.activity_key_pair.*
|
import kotlinx.android.synthetic.main.activity_seed.*
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
import org.thoughtcrime.securesms.ConversationListActivity
|
import org.thoughtcrime.securesms.ConversationListActivity
|
||||||
@ -17,20 +17,20 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
|||||||
import org.thoughtcrime.securesms.database.Address
|
import org.thoughtcrime.securesms.database.Address
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.IdentityDatabase
|
import org.thoughtcrime.securesms.database.IdentityDatabase
|
||||||
|
import org.thoughtcrime.securesms.util.Hex
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.libsignal.IdentityKeyPair
|
import org.whispersystems.curve25519.Curve25519
|
||||||
import org.whispersystems.libsignal.util.KeyHelper
|
import org.whispersystems.libsignal.util.KeyHelper
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
|
||||||
class KeyPairActivity : BaseActionBarActivity() {
|
class SeedActivity : BaseActionBarActivity() {
|
||||||
private lateinit var languageFileDirectory: File
|
private lateinit var languageFileDirectory: File
|
||||||
private var mode = Mode.Register
|
private var mode = Mode.Register
|
||||||
set(newValue) { field = newValue; updateUI() }
|
set(newValue) { field = newValue; updateUI() }
|
||||||
private var keyPair: IdentityKeyPair? = null
|
private var seed: ByteArray? = null
|
||||||
set(newValue) { field = newValue; updateMnemonic() }
|
set(newValue) { field = newValue; updateMnemonic() }
|
||||||
private var mnemonic: String? = null
|
private var mnemonic: String? = null
|
||||||
set(newValue) { field = newValue; updateMnemonicTextView() }
|
set(newValue) { field = newValue; updateMnemonicTextView() }
|
||||||
@ -42,9 +42,9 @@ class KeyPairActivity : BaseActionBarActivity() {
|
|||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_key_pair)
|
setContentView(R.layout.activity_seed)
|
||||||
setUpLanguageFileDirectory()
|
setUpLanguageFileDirectory()
|
||||||
updateKeyPair()
|
updateSeed()
|
||||||
copyButton.setOnClickListener { copy() }
|
copyButton.setOnClickListener { copy() }
|
||||||
toggleModeButton.setOnClickListener { toggleMode() }
|
toggleModeButton.setOnClickListener { toggleMode() }
|
||||||
registerOrRestoreButton.setOnClickListener { registerOrRestore() }
|
registerOrRestoreButton.setOnClickListener { registerOrRestore() }
|
||||||
@ -75,9 +75,8 @@ class KeyPairActivity : BaseActionBarActivity() {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
private fun updateKeyPair() {
|
private fun updateSeed() {
|
||||||
IdentityKeyUtil.generateIdentityKeys(this)
|
seed = Curve25519.getInstance("best").generateSeed(16)
|
||||||
keyPair = IdentityKeyUtil.getIdentityKeyPair(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateUI() {
|
private fun updateUI() {
|
||||||
@ -100,7 +99,8 @@ class KeyPairActivity : BaseActionBarActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateMnemonic() {
|
private fun updateMnemonic() {
|
||||||
mnemonic = MnemonicCodec(languageFileDirectory).encode(keyPair!!.hexEncodedPrivateKey)
|
val hexEncodedSeed = Hex.toStringCondensed(seed)
|
||||||
|
mnemonic = MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateMnemonicTextView() {
|
private fun updateMnemonicTextView() {
|
||||||
@ -124,21 +124,24 @@ class KeyPairActivity : BaseActionBarActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun registerOrRestore() {
|
private fun registerOrRestore() {
|
||||||
val keyPair: IdentityKeyPair
|
var seed: ByteArray
|
||||||
when (mode) {
|
when (mode) {
|
||||||
Mode.Register -> keyPair = this.keyPair!!
|
Mode.Register -> seed = this.seed!!
|
||||||
Mode.Restore -> {
|
Mode.Restore -> {
|
||||||
val mnemonic = mnemonicEditText.text.toString()
|
val mnemonic = mnemonicEditText.text.toString()
|
||||||
try {
|
try {
|
||||||
val hexEncodedPrivateKey = MnemonicCodec(languageFileDirectory).decode(mnemonic)
|
val hexEncodedSeed = MnemonicCodec(languageFileDirectory).decode(mnemonic)
|
||||||
IdentityKeyUtil.generateIdentityKeyPair(this, hexEncodedPrivateKey)
|
seed = Hex.fromStringCondensed(hexEncodedSeed)
|
||||||
keyPair = IdentityKeyUtil.getIdentityKeyPair(this)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
val message = if (e is MnemonicCodec.DecodingError) e.description else MnemonicCodec.DecodingError.Generic.description
|
val message = if (e is MnemonicCodec.DecodingError) e.description else MnemonicCodec.DecodingError.Generic.description
|
||||||
return Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
return Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed))
|
||||||
|
if (seed.count() == 16) seed = seed + seed
|
||||||
|
IdentityKeyUtil.generateIdentityKeyPair(this, seed)
|
||||||
|
val keyPair = IdentityKeyUtil.getIdentityKeyPair(this)
|
||||||
val publicKey = keyPair.publicKey
|
val publicKey = keyPair.publicKey
|
||||||
val hexEncodedPublicKey = keyPair.hexEncodedPublicKey
|
val hexEncodedPublicKey = keyPair.hexEncodedPublicKey
|
||||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
val registrationID = KeyHelper.generateRegistrationId(false)
|
Loading…
Reference in New Issue
Block a user