diff --git a/wallet/AndroidManifest.xml b/wallet/AndroidManifest.xml
index b4ad2b8c30..1bceb72ef1 100644
--- a/wallet/AndroidManifest.xml
+++ b/wallet/AndroidManifest.xml
@@ -97,6 +97,11 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/wallet/res/values/strings-extra.xml b/wallet/res/values/strings-extra.xml
index 7bdf760301..6b2d26149f 100644
--- a/wallet/res/values/strings-extra.xml
+++ b/wallet/res/values/strings-extra.xml
@@ -122,7 +122,7 @@
Dash address copied to clipboard
Show
\"%s\" is not a recovery phrase word
- Recovery phrase must have 12 words
+ Recovery phrase must have 12 or 24 words
Bad recovery phrase
Wallet could not be restored:\n\n%s\n\nBad recovery phrase?
@@ -473,4 +473,8 @@
Prices weren\'t retrieved. Fiat values may be incorrect.
Prices are at least 30 minutes old. Fiat values may be incorrect.
Prices have fluctuated more than 50% since the last update.
+ Select Security Level
+ You can secure your wallet with a 12 or 24 word recovery phrase.
+ Secure
+ 24 word recovery phrase
\ No newline at end of file
diff --git a/wallet/res/values/strings.xml b/wallet/res/values/strings.xml
index 5d0a76731b..b09196806a 100644
--- a/wallet/res/values/strings.xml
+++ b/wallet/res/values/strings.xml
@@ -417,5 +417,7 @@
This app is configured to continue running after not being visible for some time.\n\nWe suggest allowing this app to always stay up-to-date with the blockchain, even in the background.\n\nDon\'t worry, we will always mind your battery usage.
Open Settings
Update profile information
+ 12 word recovery phrase
+ Very secure
diff --git a/wallet/src/de/schildbach/wallet/service/WalletFactory.kt b/wallet/src/de/schildbach/wallet/service/WalletFactory.kt
index 7ae887fc86..4e957393ae 100644
--- a/wallet/src/de/schildbach/wallet/service/WalletFactory.kt
+++ b/wallet/src/de/schildbach/wallet/service/WalletFactory.kt
@@ -30,6 +30,7 @@ import org.bitcoinj.core.AddressFormatException
import org.bitcoinj.core.DumpedPrivateKey
import org.bitcoinj.core.ECKey
import org.bitcoinj.core.NetworkParameters
+import org.bitcoinj.crypto.LinuxSecureRandom
import org.bitcoinj.script.Script
import org.bitcoinj.wallet.DeterministicKeyChain
import org.bitcoinj.wallet.DeterministicSeed
@@ -49,13 +50,14 @@ import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
+import java.security.SecureRandom
import java.text.ParseException
import java.util.LinkedList
import javax.inject.Inject
interface WalletFactory {
// Onboarding
- fun create(params: NetworkParameters): Wallet
+ fun create(params: NetworkParameters, seedWordCount: Int): Wallet
fun restoreFromSeed(params: NetworkParameters, recoveryPhrase: List): Wallet
@Throws(IOException::class)
fun restoreFromFile(params: NetworkParameters, backupUri: Uri, password: String): Pair
@@ -99,8 +101,18 @@ class DashWalletFactory @Inject constructor(
}
}
- override fun create(params: NetworkParameters): Wallet {
- val wallet = WalletEx.createDeterministic(params, Script.ScriptType.P2PKH)
+ override fun create(params: NetworkParameters, seedWordCount: Int): Wallet {
+ //val wallet = WalletEx.createDeterministic(params, Script.ScriptType.P2PKH)
+ val bits = when (seedWordCount) {
+ 12 -> DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS
+ 24 -> DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS * 2
+ else -> error("only 12 or 24 words are supported when creating a wallet")
+ }
+ val wallet = WalletEx.fromSeed(
+ params,
+ DeterministicSeed(SecureRandom(), bits, ""),
+ Script.ScriptType.P2PKH
+ )
addMissingExtensions(wallet)
checkWalletValid(wallet, params)
return wallet
diff --git a/wallet/src/de/schildbach/wallet/ui/OnboardingActivity.kt b/wallet/src/de/schildbach/wallet/ui/OnboardingActivity.kt
index ef6b3de1fd..00a85c761c 100644
--- a/wallet/src/de/schildbach/wallet/ui/OnboardingActivity.kt
+++ b/wallet/src/de/schildbach/wallet/ui/OnboardingActivity.kt
@@ -26,6 +26,7 @@ import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.activity.viewModels
import androidx.core.view.isVisible
@@ -40,6 +41,7 @@ import de.schildbach.wallet.ui.main.MainActivity
import de.schildbach.wallet.security.PinRetryController
import de.schildbach.wallet_test.BuildConfig
import de.schildbach.wallet.security.SecurityGuard
+import de.schildbach.wallet.ui.onboarding.SelectSecurityLevelActivity
import de.schildbach.wallet_test.R
import de.schildbach.wallet_test.databinding.ActivityOnboardingBinding
import de.schildbach.wallet_test.databinding.ActivityOnboardingPermLockBinding
@@ -111,6 +113,16 @@ class OnboardingActivity : RestoreFromFileActivity() {
@Inject
lateinit var pinRetryController: PinRetryController
+ private val selectWordCountLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ val onboardingInvite = intent.getParcelableExtra(EXTRA_INVITE)
+ viewModel.createNewWallet(
+ onboardingInvite,
+ result.data!!.extras!!.getInt(SelectSecurityLevelActivity.EXTRA_WORD_COUNT)
+ )
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -243,8 +255,9 @@ class OnboardingActivity : RestoreFromFileActivity() {
private fun initView() {
binding.createNewWallet.setOnClickListener {
- val onboardingInvite = intent.getParcelableExtra(EXTRA_INVITE)
- viewModel.createNewWallet(onboardingInvite)
+ selectWordCountLauncher.launch(
+ Intent(this, SelectSecurityLevelActivity::class.java)
+ )
}
binding.recoveryWallet.setOnClickListener {
walletApplication.initEnvironmentIfNeeded()
diff --git a/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt b/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt
index c4d869bdfc..db95e959ec 100644
--- a/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt
+++ b/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt
@@ -56,9 +56,9 @@ class OnboardingViewModel @Inject constructor(
internal val finishUnecryptedWalletUpgradeAction = SingleLiveEvent()
internal val startActivityAction = SingleLiveEvent()
- fun createNewWallet(onboardingInvite: InvitationLinkData?) {
+ fun createNewWallet(onboardingInvite: InvitationLinkData?, seedWordCount: Int) {
walletApplication.initEnvironmentIfNeeded()
- val wallet = walletFactory.create(Constants.NETWORK_PARAMETERS)
+ val wallet = walletFactory.create(Constants.NETWORK_PARAMETERS, seedWordCount)
log.info("successfully created new wallet")
walletApplication.setWallet(wallet)
configuration.armBackupSeedReminder()
diff --git a/wallet/src/de/schildbach/wallet/ui/dashpay/utils/GoogleDriveService.kt b/wallet/src/de/schildbach/wallet/ui/dashpay/utils/GoogleDriveService.kt
index 0f22f6fd59..ad1266cede 100644
--- a/wallet/src/de/schildbach/wallet/ui/dashpay/utils/GoogleDriveService.kt
+++ b/wallet/src/de/schildbach/wallet/ui/dashpay/utils/GoogleDriveService.kt
@@ -116,7 +116,7 @@ object GoogleDriveService {
fun getSigninAccount(context: Context?): GoogleSignInAccount? {
val opts = getGoogleSigninOptions()
- val account = GoogleSignIn.getLastSignedInAccount(context)
+ val account = GoogleSignIn.getLastSignedInAccount(context!!)
val permissions = arrayOf(Scope(DriveScopes.DRIVE_FILE))
return if (GoogleSignIn.hasPermissions(account, *permissions)) {
account
diff --git a/wallet/src/de/schildbach/wallet/ui/onboarding/SelectSecurityLevelActivity.kt b/wallet/src/de/schildbach/wallet/ui/onboarding/SelectSecurityLevelActivity.kt
new file mode 100644
index 0000000000..295494ec54
--- /dev/null
+++ b/wallet/src/de/schildbach/wallet/ui/onboarding/SelectSecurityLevelActivity.kt
@@ -0,0 +1,52 @@
+package de.schildbach.wallet.ui.onboarding
+
+import android.content.Intent
+import android.os.Bundle
+import de.schildbach.wallet_test.databinding.ActivityPhrasewordcountBinding
+import org.dash.wallet.common.SecureActivity
+
+class SelectSecurityLevelActivity : SecureActivity() {
+ private lateinit var binding: ActivityPhrasewordcountBinding
+ private var selectedWordCount: Int = 12
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityPhrasewordcountBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.titleBar.setOnClickListener {
+ setResult(RESULT_CANCELED)
+ finish()
+ }
+
+ binding.twelveWordsOption.setOnClickListener {
+ setMode(12)
+ }
+
+ binding.twentyFourWordsOption.setOnClickListener {
+ setMode(24)
+ }
+
+ binding.continueBtn.setOnClickListener {
+ setResult(RESULT_OK, Intent().apply { putExtra(EXTRA_WORD_COUNT, selectedWordCount) })
+ finish()
+ }
+ setMode(12)
+ }
+
+ private fun setMode(wordCount: Int) {
+ if (wordCount == 12) {
+ binding.twelveWordsOption.isSelected = true
+ binding.twentyFourWordsOption.isSelected = false
+ selectedWordCount = 12
+ } else {
+ binding.twelveWordsOption.isSelected = false
+ binding.twentyFourWordsOption.isSelected = true
+ selectedWordCount = 24
+ }
+ }
+
+ companion object {
+ const val EXTRA_WORD_COUNT = "extra_word_count"
+ }
+}
\ No newline at end of file
diff --git a/wallet/src/de/schildbach/wallet/util/MnemonicCodeExt.kt b/wallet/src/de/schildbach/wallet/util/MnemonicCodeExt.kt
index d654af69de..89c56287d7 100644
--- a/wallet/src/de/schildbach/wallet/util/MnemonicCodeExt.kt
+++ b/wallet/src/de/schildbach/wallet/util/MnemonicCodeExt.kt
@@ -60,8 +60,8 @@ class MnemonicCodeExt(wordstream: InputStream, wordListDigest: String?) : Mnemon
@Throws(MnemonicException::class)
fun check(context: Context, words: List) {
- if (words.size != 12) {
- throw MnemonicException.MnemonicLengthException("Word list size must be 12")
+ if (words.size != 12 && words.size != 24) {
+ throw MnemonicException.MnemonicLengthException("Word list size must be 12 or 24")
}
try {
check(words)