Fix restoration from seed issue

pull/373/head
nielsandriesse 4 years ago
parent eddd6dc0e6
commit 9102215ca0

@ -336,7 +336,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
case PREFERENCE_CATEGORY_LINKED_DEVICES: break; case PREFERENCE_CATEGORY_LINKED_DEVICES: break;
case PREFERENCE_CATEGORY_SEED: case PREFERENCE_CATEGORY_SEED:
try { try {
String hexEncodedSeed = IdentityKeyUtil.retrieve(getContext(), IdentityKeyUtil.lokiSeedKey); String hexEncodedSeed = IdentityKeyUtil.retrieve(getContext(), IdentityKeyUtil.LOKI_SEED);
if (hexEncodedSeed == null) { if (hexEncodedSeed == null) {
hexEncodedSeed = HexEncodingKt.getHexEncodedPrivateKey(IdentityKeyUtil.getIdentityKeyPair(getContext())); // Legacy account hexEncodedSeed = HexEncodingKt.getHexEncodedPrivateKey(IdentityKeyUtil.getIdentityKeyPair(getContext())); // Legacy account
} }

@ -53,8 +53,7 @@ public class IdentityKeyUtil {
public static final String IDENTITY_PRIVATE_KEY_PREF = "pref_identity_private_v3"; public static final String IDENTITY_PRIVATE_KEY_PREF = "pref_identity_private_v3";
public static final String ED25519_PUBLIC_KEY = "pref_ed25519_public_key"; 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 ED25519_SECRET_KEY = "pref_ed25519_secret_key";
public static final String LOKI_SEED = "loki_seed";
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);

@ -85,7 +85,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
seed = seedCandidate seed = seedCandidate
} }
generateKeyPair() generateKeyPair()
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed)) IdentityKeyUtil.save(this, IdentityKeyUtil.LOKI_SEED, Hex.toStringCondensed(seed))
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(keyPair!!.publicKey.serialize())) IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(keyPair!!.publicKey.serialize()))
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair!!.privateKey.serialize())) IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair!!.privateKey.serialize()))
val userHexEncodedPublicKey = keyPair!!.hexEncodedPublicKey val userHexEncodedPublicKey = keyPair!!.hexEncodedPublicKey
@ -140,7 +140,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
} }
private fun reset() { private fun reset() {
IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey) IdentityKeyUtil.delete(this, IdentityKeyUtil.LOKI_SEED)
TextSecurePreferences.removeLocalNumber(this) TextSecurePreferences.removeLocalNumber(this)
TextSecurePreferences.setHasSeenWelcomeScreen(this, false) TextSecurePreferences.setHasSeenWelcomeScreen(this, false)
TextSecurePreferences.setPromptedPushRegistration(this, false) TextSecurePreferences.setPromptedPushRegistration(this, false)

@ -26,6 +26,7 @@ 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.loki.utilities.KeyPairUtilities
import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.Base64
@ -37,7 +38,6 @@ import org.whispersystems.libsignal.util.KeyHelper
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
class RegisterActivity : BaseActionBarActivity() { class RegisterActivity : BaseActionBarActivity() {
private val sodium = LazySodiumAndroid(SodiumAndroid())
private var seed: ByteArray? = null private var seed: ByteArray? = null
private var ed25519KeyPair: KeyPair? = null private var ed25519KeyPair: KeyPair? = null
private var x25519KeyPair: ECKeyPair? = null private var x25519KeyPair: ECKeyPair? = null
@ -73,16 +73,10 @@ class RegisterActivity : BaseActionBarActivity() {
// region Updating // region Updating
private fun updateKeyPair() { private fun updateKeyPair() {
val seedCandidate = Curve25519.getInstance(Curve25519.BEST).generateSeed(16) val keyPairGenerationResult = KeyPairUtilities.generate()
try { seed = keyPairGenerationResult.seed
val padding = ByteArray(16) { 0 } ed25519KeyPair = keyPairGenerationResult.ed25519KeyPair
ed25519KeyPair = sodium.cryptoSignSeedKeypair(seedCandidate + padding) x25519KeyPair = keyPairGenerationResult.x25519KeyPair
val x25519KeyPair = sodium.convertKeyPairEd25519ToCurve25519(ed25519KeyPair)
this.x25519KeyPair = ECKeyPair(DjbECPublicKey(x25519KeyPair.publicKey.asBytes), DjbECPrivateKey(x25519KeyPair.secretKey.asBytes))
} catch (exception: Exception) {
return updateKeyPair()
}
seed = seedCandidate
} }
private fun updatePublicKeyTextView() { private fun updatePublicKeyTextView() {
@ -117,11 +111,7 @@ class RegisterActivity : BaseActionBarActivity() {
// region Interaction // region Interaction
private fun register() { private fun register() {
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed)) KeyPairUtilities.store(this, seed!!, ed25519KeyPair!!, x25519KeyPair!!)
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(x25519KeyPair!!.publicKey.serialize()))
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(x25519KeyPair!!.privateKey.serialize()))
IdentityKeyUtil.save(this, IdentityKeyUtil.ED25519_PUBLIC_KEY, Base64.encodeBytes(ed25519KeyPair!!.publicKey.asBytes))
IdentityKeyUtil.save(this, IdentityKeyUtil.ED25519_SECRET_KEY, Base64.encodeBytes(ed25519KeyPair!!.secretKey.asBytes))
val userHexEncodedPublicKey = x25519KeyPair!!.hexEncodedPublicKey val userHexEncodedPublicKey = x25519KeyPair!!.hexEncodedPublicKey
val registrationID = KeyHelper.generateRegistrationId(false) val registrationID = KeyHelper.generateRegistrationId(false)
TextSecurePreferences.setLocalRegistrationId(this, registrationID) TextSecurePreferences.setLocalRegistrationId(this, registrationID)

@ -18,18 +18,15 @@ 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.loki.utilities.KeyPairUtilities
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.Base64
import org.thoughtcrime.securesms.util.Hex import org.thoughtcrime.securesms.util.Hex
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.libsignal.ecc.Curve
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.hexEncodedPublicKey import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
import java.io.File
import java.io.FileOutputStream
class RestoreActivity : BaseActionBarActivity() { class RestoreActivity : BaseActionBarActivity() {
@ -68,13 +65,11 @@ class RestoreActivity : BaseActionBarActivity() {
MnemonicUtilities.loadFileContents(this, fileName) MnemonicUtilities.loadFileContents(this, fileName)
} }
val hexEncodedSeed = MnemonicCodec(loadFileContents).decode(mnemonic) val hexEncodedSeed = MnemonicCodec(loadFileContents).decode(mnemonic)
var seed = Hex.fromStringCondensed(hexEncodedSeed) val seed = Hex.fromStringCondensed(hexEncodedSeed)
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed)) val keyPairGenerationResult = KeyPairUtilities.generate(seed)
if (seed.size == 16) { seed = seed + seed } val x25519KeyPair = keyPairGenerationResult.x25519KeyPair
val keyPair = Curve.generateKeyPair(seed) KeyPairUtilities.store(this, seed, keyPairGenerationResult.ed25519KeyPair, x25519KeyPair)
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(keyPair.publicKey.serialize())) val userHexEncodedPublicKey = x25519KeyPair.hexEncodedPublicKey
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair.privateKey.serialize()))
val userHexEncodedPublicKey = keyPair.hexEncodedPublicKey
val registrationID = KeyHelper.generateRegistrationId(false) val registrationID = KeyHelper.generateRegistrationId(false)
TextSecurePreferences.setLocalRegistrationId(this, registrationID) TextSecurePreferences.setLocalRegistrationId(this, registrationID)
DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey), DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey),

@ -7,7 +7,6 @@ import android.os.Bundle
import android.text.Spannable import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.util.Log
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.Toast import android.widget.Toast
import kotlinx.android.synthetic.main.activity_seed.* import kotlinx.android.synthetic.main.activity_seed.*
@ -19,12 +18,11 @@ import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
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.hexEncodedPrivateKey
import java.io.File
class SeedActivity : BaseActionBarActivity() { class SeedActivity : BaseActionBarActivity() {
private val seed by lazy { private val seed by lazy {
var hexEncodedSeed = IdentityKeyUtil.retrieve(this, IdentityKeyUtil.lokiSeedKey) var hexEncodedSeed = IdentityKeyUtil.retrieve(this, IdentityKeyUtil.LOKI_SEED)
if (hexEncodedSeed == null) { if (hexEncodedSeed == null) {
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(this).hexEncodedPrivateKey // Legacy account hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(this).hexEncodedPrivateKey // Legacy account
} }

@ -8,7 +8,6 @@ import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.WindowManager
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
@ -23,7 +22,7 @@ import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey
class SeedDialog : DialogFragment() { class SeedDialog : DialogFragment() {
private val seed by lazy { private val seed by lazy {
var hexEncodedSeed = IdentityKeyUtil.retrieve(requireContext(), IdentityKeyUtil.lokiSeedKey) var hexEncodedSeed = IdentityKeyUtil.retrieve(requireContext(), IdentityKeyUtil.LOKI_SEED)
if (hexEncodedSeed == null) { if (hexEncodedSeed == null) {
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(requireContext()).hexEncodedPrivateKey // Legacy account hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(requireContext()).hexEncodedPrivateKey // Legacy account
} }

@ -0,0 +1,48 @@
package org.thoughtcrime.securesms.loki.utilities
import android.content.Context
import com.goterl.lazycode.lazysodium.LazySodiumAndroid
import com.goterl.lazycode.lazysodium.SodiumAndroid
import com.goterl.lazycode.lazysodium.utils.KeyPair
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.util.Base64
import org.thoughtcrime.securesms.util.Hex
import org.whispersystems.curve25519.Curve25519
import org.whispersystems.libsignal.ecc.DjbECPrivateKey
import org.whispersystems.libsignal.ecc.DjbECPublicKey
import org.whispersystems.libsignal.ecc.ECKeyPair
object KeyPairUtilities {
data class KeyPairGenerationResult(
val seed: ByteArray,
val ed25519KeyPair: KeyPair,
val x25519KeyPair: ECKeyPair
)
fun generate(): KeyPairGenerationResult {
val seed = Curve25519.getInstance(Curve25519.BEST).generateSeed(16)
try {
return generate(seed)
} catch (exception: Exception) {
return generate()
}
}
fun generate(seed: ByteArray): KeyPairGenerationResult {
val sodium = LazySodiumAndroid(SodiumAndroid())
val padding = ByteArray(16) { 0 }
val ed25519KeyPair = sodium.cryptoSignSeedKeypair(seed + padding)
val sodiumX25519KeyPair = sodium.convertKeyPairEd25519ToCurve25519(ed25519KeyPair)
val x25519KeyPair = ECKeyPair(DjbECPublicKey(sodiumX25519KeyPair.publicKey.asBytes), DjbECPrivateKey(sodiumX25519KeyPair.secretKey.asBytes))
return KeyPairGenerationResult(seed, ed25519KeyPair, x25519KeyPair)
}
fun store(context: Context, seed: ByteArray, ed25519KeyPair: KeyPair, x25519KeyPair: ECKeyPair) {
IdentityKeyUtil.save(context, IdentityKeyUtil.LOKI_SEED, Hex.toStringCondensed(seed))
IdentityKeyUtil.save(context, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(x25519KeyPair.publicKey.serialize()))
IdentityKeyUtil.save(context, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(x25519KeyPair.privateKey.serialize()))
IdentityKeyUtil.save(context, IdentityKeyUtil.ED25519_PUBLIC_KEY, Base64.encodeBytes(ed25519KeyPair.publicKey.asBytes))
IdentityKeyUtil.save(context, IdentityKeyUtil.ED25519_SECRET_KEY, Base64.encodeBytes(ed25519KeyPair.secretKey.asBytes))
}
}
Loading…
Cancel
Save