Skip to content

Commit

Permalink
feat: passcode (#984)
Browse files Browse the repository at this point in the history
* Passphrase feature

* Security rep and fraud protection

* Few fixes
  • Loading branch information
alexandrVakhtinTari authored Oct 16, 2023
1 parent 36b1d78 commit 4db09b1
Show file tree
Hide file tree
Showing 48 changed files with 1,483 additions and 406 deletions.
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
<activity
android:name=".ui.fragment.auth.AuthActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/AppTheme.Auth"
android:theme="@style/AppTheme.Light"
android:windowSoftInputMode="stateAlwaysHidden" /> <!-- home (transaction list) -->
<activity
android:name=".ui.fragment.home.HomeActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.lifecycle.ProcessLifecycleOwner
import com.orhanobut.logger.Logger
import com.tari.android.wallet.BuildConfig
import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.security.SecurityPrefRepository
import com.tari.android.wallet.di.DiContainer
import com.tari.android.wallet.event.Event
import com.tari.android.wallet.event.EventBus
Expand Down Expand Up @@ -72,6 +73,9 @@ class TariWalletApplication : Application() {
@Inject
lateinit var sharedPrefsRepository: SharedPrefsRepository

@Inject
lateinit var securityPrefRepository: SecurityPrefRepository

@Inject
lateinit var walletServiceLauncher: WalletServiceLauncher

Expand Down Expand Up @@ -126,7 +130,7 @@ class TariWalletApplication : Application() {
notificationHelper.createNotificationChannels()

// user should authenticate every time the app starts up
sharedPrefsRepository.isAuthenticated = false
securityPrefRepository.isAuthenticated = false

registerReceiver(connectionStateReceiver, connectionStateReceiver.intentFilter)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import com.tari.android.wallet.data.WalletConfig
import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.baseNode.BaseNodeSharedRepository
import com.tari.android.wallet.data.sharedPrefs.network.NetworkRepository
import com.tari.android.wallet.data.sharedPrefs.security.SecurityPrefRepository
import com.tari.android.wallet.data.sharedPrefs.tariSettings.TariSettingsSharedRepository
import com.tari.android.wallet.event.EventBus
import com.tari.android.wallet.ffi.*
Expand All @@ -64,7 +65,8 @@ class WalletManager(
private val baseNodeSharedRepository: BaseNodeSharedRepository,
private val seedPhraseRepository: SeedPhraseRepository,
private val networkRepository: NetworkRepository,
private var tariSettingsSharedRepository: TariSettingsSharedRepository,
private val tariSettingsSharedRepository: TariSettingsSharedRepository,
private val securityPrefRepository: SecurityPrefRepository,
private val baseNodes: BaseNodes,
private val torConfig: TorConfig
) {
Expand Down Expand Up @@ -202,6 +204,7 @@ class WalletManager(
val isNewInstallation = !WalletUtil.walletExists(walletConfig)
val wallet = FFIWallet(
sharedPrefsWrapper,
securityPrefRepository,
seedPhraseRepository,
networkRepository,
getCommsConfig(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.tari.android.wallet.application.securityStage
import android.text.SpannableString
import android.text.Spanned
import com.tari.android.wallet.R
import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.securityStages.DisabledTimestampsDto
import com.tari.android.wallet.data.sharedPrefs.securityStages.SecurityStagesRepository
import com.tari.android.wallet.data.sharedPrefs.securityStages.WalletSecurityStage
Expand Down Expand Up @@ -35,9 +34,6 @@ class StagedWalletSecurityManager : CommonViewModel() {
@Inject
lateinit var backupPrefsRepository: BackupSettingsRepository

@Inject
lateinit var sharedPrefsRepository: SharedPrefsRepository

init {
component.inject(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@
*/
package com.tari.android.wallet.data.sharedPrefs

import android.content.Context
import android.content.SharedPreferences
import com.tari.android.wallet.data.repository.CommonRepository
import com.tari.android.wallet.data.sharedPrefs.baseNode.BaseNodeSharedRepository
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefBooleanDelegate
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefStringDelegate
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefStringSecuredDelegate
import com.tari.android.wallet.data.sharedPrefs.network.NetworkRepository
import com.tari.android.wallet.data.sharedPrefs.network.formatKey
import com.tari.android.wallet.data.sharedPrefs.security.SecurityPrefRepository
import com.tari.android.wallet.data.sharedPrefs.securityStages.SecurityStagesRepository
import com.tari.android.wallet.data.sharedPrefs.sentry.SentryPrefRepository
import com.tari.android.wallet.data.sharedPrefs.tariSettings.TariSettingsSharedRepository
Expand All @@ -61,7 +60,6 @@ import kotlin.random.Random

@Singleton
class SharedPrefsRepository @Inject constructor(
context: Context,
sharedPrefs: SharedPreferences,
networkRepository: NetworkRepository,
private val backupSettingsRepository: BackupSettingsRepository,
Expand All @@ -71,12 +69,12 @@ class SharedPrefsRepository @Inject constructor(
private val tariSettingsSharedRepository: TariSettingsSharedRepository,
private val securityStagesRepository: SecurityStagesRepository,
private val contactSharedPrefRepository: ContactSharedPrefRepository,
private val sentryPrefRepository: SentryPrefRepository
private val sentryPrefRepository: SentryPrefRepository,
private val securityPrefRepository: SecurityPrefRepository
) : CommonRepository(networkRepository) {

private object Key {
const val publicKeyHexString = "tari_wallet_public_key_hex_string"
const val isAuthenticated = "tari_wallet_is_authenticated"
const val emojiId = "tari_wallet_emoji_id_"
const val name = "tari_wallet_name_"
const val surname = "tari_wallet_surname_"
Expand All @@ -86,22 +84,17 @@ class SharedPrefsRepository @Inject constructor(
const val onboardingAuthSetupStarted = "tari_wallet_onboarding_auth_setup_started"
const val onboardingCompleted = "tari_wallet_onboarding_completed"
const val onboardingDisplayedAtHome = "tari_wallet_onboarding_displayed_at_home"
const val walletDatabasePassphrase = "tari_wallet_database_passphrase"
const val isDataCleared = "tari_is_data_cleared"
}

var publicKeyHexString: String? by SharedPrefStringDelegate(sharedPrefs, this, formatKey(Key.publicKeyHexString))

var isAuthenticated: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.isAuthenticated))

var emojiId: String? by SharedPrefStringDelegate(sharedPrefs, this, formatKey(Key.emojiId))

var name: String? by SharedPrefStringDelegate(sharedPrefs, this, formatKey(Key.name))

var surname: String? by SharedPrefStringDelegate(sharedPrefs, this, formatKey(Key.surname))

var databasePassphrase: String? by SharedPrefStringSecuredDelegate(context, sharedPrefs, this, formatKey(Key.walletDatabasePassphrase))

var onboardingStarted: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.onboardingStarted))

var onboardingCompleted: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.onboardingCompleted))
Expand Down Expand Up @@ -131,15 +124,15 @@ class SharedPrefsRepository @Inject constructor(
securityStagesRepository.clear()
contactSharedPrefRepository.clear()
sentryPrefRepository.clear()
securityPrefRepository.clear()
publicKeyHexString = null
isAuthenticated = false
emojiId = null
databasePassphrase = null
onboardingStarted = false
onboardingCompleted = false
onboardingAuthSetupStarted = false
onboardingAuthSetupCompleted = false
onboardingDisplayedAtHome = false

}

fun generateDatabasePassphrase(): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.tari.android.wallet.data.sharedPrefs.security

class LoginAttemptDto(val timeInMills: Long, val isSuccessful: Boolean)

class LoginAttemptList : ArrayList<LoginAttemptDto>()

fun LoginAttemptList?.orEmpty() : LoginAttemptList = this ?: LoginAttemptList()
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.tari.android.wallet.data.sharedPrefs.security

import android.content.Context
import android.content.SharedPreferences
import com.tari.android.wallet.data.repository.CommonRepository
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefBooleanDelegate
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefBooleanNullableDelegate
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefGsonDelegate
import com.tari.android.wallet.data.sharedPrefs.delegates.SharedPrefStringSecuredDelegate
import com.tari.android.wallet.data.sharedPrefs.network.NetworkRepository
import com.tari.android.wallet.data.sharedPrefs.network.formatKey
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class SecurityPrefRepository @Inject constructor(
context: Context,
sharedPrefs: SharedPreferences,
networkRepository: NetworkRepository,
) : CommonRepository(networkRepository) {

companion object Key {
const val isAuthenticatedKey = "tari_wallet_is_authenticated"
const val isFeatureAuthenticatedKey = "tari_wallet_is_feature_authenticated"
const val pinCodeKey = "tari_is_pincode"
const val biometricsKey = "tari_is_biometrics"
const val walletDatabasePassphraseKey = "tari_wallet_database_passphrase"
const val loginAttemptsKey = "tari_login_attempts"
}

var isAuthenticated: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(isAuthenticatedKey))

var isFeatureAuthenticated: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(isFeatureAuthenticatedKey))

var pinCode: String? by SharedPrefStringSecuredDelegate(context, sharedPrefs, this, formatKey(pinCodeKey), null)

var biometricsAuth: Boolean? by SharedPrefBooleanNullableDelegate(sharedPrefs, this, formatKey(biometricsKey))

var databasePassphrase: String? by SharedPrefStringSecuredDelegate(context, sharedPrefs, this, formatKey(walletDatabasePassphraseKey))

var attempts: LoginAttemptList? by SharedPrefGsonDelegate<LoginAttemptList>(
sharedPrefs,
this,
formatKey(loginAttemptsKey),
LoginAttemptList::class.java,
LoginAttemptList()
)

fun saveAttempt(attempt: LoginAttemptDto) {
this.attempts = attempts.orEmpty().apply {
add(attempt)
}
if (attempt.isSuccessful) {
attempts = null
}
}

fun clear() {
databasePassphrase = null
isAuthenticated = false
isFeatureAuthenticated = false
pinCode = null
biometricsAuth = null
attempts = null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import com.tari.android.wallet.ui.component.clipboardController.WalletAddressVie
import com.tari.android.wallet.ui.component.networkStateIndicator.ConnectionIndicatorViewModel
import com.tari.android.wallet.ui.fragment.auth.AuthActivity
import com.tari.android.wallet.ui.fragment.auth.AuthViewModel
import com.tari.android.wallet.ui.fragment.biometrics.ChangeBiometricsViewModel
import com.tari.android.wallet.ui.fragment.chat_list.ChatListViewModel
import com.tari.android.wallet.ui.fragment.chat_list.chat.ChatViewModel
import com.tari.android.wallet.ui.fragment.contact_book.contactSelection.ContactSelectionViewModel
Expand All @@ -59,6 +60,7 @@ import com.tari.android.wallet.ui.fragment.onboarding.activity.OnboardingFlowAct
import com.tari.android.wallet.ui.fragment.onboarding.createWallet.CreateWalletViewModel
import com.tari.android.wallet.ui.fragment.onboarding.inroduction.IntroductionViewModel
import com.tari.android.wallet.ui.fragment.onboarding.localAuth.LocalAuthViewModel
import com.tari.android.wallet.ui.fragment.pinCode.EnterPinCodeViewModel
import com.tari.android.wallet.ui.fragment.profile.WalletInfoViewModel
import com.tari.android.wallet.ui.fragment.qr.QRScannerActivity
import com.tari.android.wallet.ui.fragment.qr.QRScannerViewModel
Expand Down Expand Up @@ -203,6 +205,8 @@ interface ApplicationComponent {
fun inject(viewModel: ChatListViewModel)
fun inject(viewModel: ChatViewModel)
fun inject(viewModel: DataCollectionViewModel)
fun inject(viewModel: EnterPinCodeViewModel)
fun inject(viewModel: ChangeBiometricsViewModel)

fun getClipboardManager(): ClipboardManager
}
5 changes: 3 additions & 2 deletions app/src/main/java/com/tari/android/wallet/di/WalletModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ import com.tari.android.wallet.data.WalletConfig
import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.baseNode.BaseNodeSharedRepository
import com.tari.android.wallet.data.sharedPrefs.network.NetworkRepository
import com.tari.android.wallet.data.sharedPrefs.security.SecurityPrefRepository
import com.tari.android.wallet.data.sharedPrefs.tariSettings.TariSettingsSharedRepository
import com.tari.android.wallet.infrastructure.logging.BugReportingService
import com.tari.android.wallet.network.NetworkConnectionStateReceiver
import com.tari.android.wallet.service.seedPhrase.SeedPhraseRepository
import com.tari.android.wallet.tor.TorConfig
import com.tari.android.wallet.tor.TorProxyManager
Expand All @@ -63,6 +62,7 @@ class WalletModule {
baseNodeSharedRepository: BaseNodeSharedRepository,
seedPhraseRepository: SeedPhraseRepository,
networkRepository: NetworkRepository,
securityPrefRepository: SecurityPrefRepository,
tariSettingsSharedRepository: TariSettingsSharedRepository,
baseNodes: BaseNodes
): WalletManager = WalletManager(
Expand All @@ -73,6 +73,7 @@ class WalletModule {
seedPhraseRepository,
networkRepository,
tariSettingsSharedRepository,
securityPrefRepository,
baseNodes,
torConfig
)
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/java/com/tari/android/wallet/ffi/FFIWallet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ package com.tari.android.wallet.ffi

import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.network.NetworkRepository
import com.tari.android.wallet.data.sharedPrefs.security.SecurityPrefRepository
import com.tari.android.wallet.model.*
import com.tari.android.wallet.model.recovery.WalletRestorationResult
import com.tari.android.wallet.service.seedPhrase.SeedPhraseRepository
Expand All @@ -50,6 +51,7 @@ import java.util.concurrent.atomic.AtomicReference

class FFIWallet(
val sharedPrefsRepository: SharedPrefsRepository,
val securityPrefRepository: SecurityPrefRepository,
val seedPhraseRepository: SeedPhraseRepository,
val networkRepository: NetworkRepository,
val commsConfig: FFICommsConfig,
Expand Down Expand Up @@ -224,10 +226,10 @@ class FFIWallet(
val error = FFIError()
logger.i("Pre jniCreate")

var passphrase = sharedPrefsRepository.databasePassphrase
var passphrase = securityPrefRepository.databasePassphrase
if (passphrase.isNullOrEmpty()) {
passphrase = sharedPrefsRepository.generateDatabasePassphrase()
sharedPrefsRepository.databasePassphrase = passphrase
securityPrefRepository.databasePassphrase = passphrase
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ package com.tari.android.wallet.infrastructure.backup
import com.google.gson.Gson
import com.orhanobut.logger.Logger
import com.tari.android.wallet.data.WalletConfig
import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.security.SecurityPrefRepository
import com.tari.android.wallet.extension.encrypt
import com.tari.android.wallet.ffi.FFIError
import com.tari.android.wallet.ffi.FFIWallet
Expand All @@ -54,7 +54,7 @@ import javax.inject.Singleton
@Singleton
class BackupFileProcessor @Inject constructor(
private val backupSettingsRepository: BackupSettingsRepository,
private val sharedPrefsRepository: SharedPrefsRepository,
private val securityPrefRepository: SecurityPrefRepository,
private val walletConfig: WalletConfig,
private val namingPolicy: BackupNamingPolicy,
) {
Expand Down Expand Up @@ -88,7 +88,7 @@ class BackupFileProcessor @Inject constructor(
logger.i("Partial files was generated")
return Triple(outputFile, backupDate, mimeType)
} else {
val passphrase = sharedPrefsRepository.databasePassphrase!!
val passphrase = securityPrefRepository.databasePassphrase!!
val passphraseFile = File(walletConfig.getWalletTempDirPath(), namingPolicy.getPassphraseFileName())
passphraseFile.bufferedWriter().use { it.append(passphrase) }

Expand Down Expand Up @@ -133,7 +133,7 @@ class BackupFileProcessor @Inject constructor(
val passphraseFile = File(walletConfig.getWalletFilesDirPath(), namingPolicy.getPassphraseFileName())
val passphrase = passphraseFile.readText()

sharedPrefsRepository.databasePassphrase = passphrase
securityPrefRepository.databasePassphrase = passphrase

unencryptedCompressedFile.delete()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import android.bluetooth.le.AdvertiseSettings
import android.os.ParcelUuid
import com.tari.android.wallet.application.deeplinks.DeepLink
import com.tari.android.wallet.application.deeplinks.DeeplinkHandler
import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository
import com.tari.android.wallet.data.sharedPrefs.bluetooth.BluetoothServerState
import com.tari.android.wallet.data.sharedPrefs.bluetooth.ShareSettingsRepository
import com.tari.android.wallet.extension.addTo
Expand All @@ -32,9 +31,7 @@ import javax.inject.Singleton
class TariBluetoothServer @Inject constructor(
private val shareSettingsRepository: ShareSettingsRepository,
val deeplinkHandler: DeeplinkHandler,
val sharedPrefsRepository: SharedPrefsRepository
) :
TariBluetoothAdapter() {
) : TariBluetoothAdapter() {

private var bluetoothGattServer: BluetoothGattServer? = null

Expand Down
Loading

0 comments on commit 4db09b1

Please sign in to comment.