-
Notifications
You must be signed in to change notification settings - Fork 2
/
AuthPreferences.kt
199 lines (163 loc) · 7.82 KB
/
AuthPreferences.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package com.concordium.wallet.data.preferences
import android.content.Context
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import com.concordium.wallet.App
import com.concordium.wallet.util.toHex
import javax.crypto.SecretKey
class AuthPreferences(val context: Context) :
Preferences(context, SharedPreferencesKeys.PREF_FILE_AUTH.key, Context.MODE_PRIVATE) {
companion object {
const val PREFKEY_HAS_SETUP_USER = "PREFKEY_HAS_SETUP_USER"
const val PREFKEY_USE_PASSCODE = "PREFKEY_USE_PASSCODE"
const val PREFKEY_USE_BIOMETRICS = "PREFKEY_USE_BIOMETRICS"
const val PREFKEY_PASSWORD_CHECK = "PREFKEY_PASSWORD_CHECK"
const val PREFKEY_PASSWORD_CHECK_ENCRYPTED = "PREFKEY_PASSWORD_CHECK_ENCRYPTED"
const val PREFKEY_PASSWORD_ENCRYPTION_SALT = "PREFKEY_PASSWORD_ENCRYPTION_SALT"
const val PREFKEY_PASSWORD_ENCRYPTION_INITVECTOR = "PREFKEY_PASSWORD_ENCRYPTION_INITVECTOR"
const val PREFKEY_ENCRYPTED_PASSWORD = "PREFKEY_ENCRYPTED_PASSWORD_DERIVED_KEY"
const val PREFKEY_ENCRYPTED_PASSWORD_DERIVED_KEY_INITVECTOR =
"PREFKEY_ENCRYPTED_PASSWORD_DERIVED_KEY_INITVECTOR"
const val PREFKEY_BIOMETRIC_KEY = "PREFKEY_BIOMETRIC_KEY"
const val PREFKEY_TERMS_HASHED = "PREFKEY_TERMS_HASHED"
const val PREFKEY_SHIELDING_ENABLED_ = "PREFKEY_SHIELDING_ENABLED_"
const val PREFKEY_IDENTITY_PENDING_ACKNOWLEDGED = "PREFKEY_IDENTITY_PENDING_ACKNOWLEDGED_"
const val SEED_PHRASE = "SEED_PHRASE"
const val SEED_PHRASE_ENCRYPTED = "SEED_PHRASE_ENCRYPTED"
}
fun setHasSetupUser(value: Boolean) {
setBoolean(PREFKEY_HAS_SETUP_USER, value)
}
fun getHasSetupUser(): Boolean {
return getBoolean(PREFKEY_HAS_SETUP_USER)
}
fun setUsePasscode(appendix: String, value: Boolean) {
setBoolean(PREFKEY_USE_PASSCODE + appendix, value)
}
fun getUsePasscode(appendix: String): Boolean {
return getBoolean(PREFKEY_USE_PASSCODE + appendix)
}
fun setUseBiometrics(appendix: String, value: Boolean) {
setBoolean(PREFKEY_USE_BIOMETRICS + appendix, value)
}
fun getUseBiometrics(appendix: String): Boolean {
return getBoolean(PREFKEY_USE_BIOMETRICS + appendix)
}
fun setPasswordCheck(appendix: String, value: String) {
setString(PREFKEY_PASSWORD_CHECK + appendix, value)
}
fun getPasswordCheck(appendix: String): String? {
return getString(PREFKEY_PASSWORD_CHECK + appendix)
}
fun setPasswordCheckEncrypted(appendix: String, value: String) {
setString(PREFKEY_PASSWORD_CHECK_ENCRYPTED + appendix, value)
}
fun getPasswordCheckEncrypted(appendix: String): String {
return getString(PREFKEY_PASSWORD_CHECK_ENCRYPTED + appendix, "")
}
fun setPasswordEncryptionSalt(appendix: String, value: String) {
setString(PREFKEY_PASSWORD_ENCRYPTION_SALT + appendix, value)
}
fun getPasswordEncryptionSalt(appendix: String): String {
return getString(PREFKEY_PASSWORD_ENCRYPTION_SALT + appendix, "")
}
fun setPasswordEncryptionInitVector(appendix: String, value: String) {
setString(PREFKEY_PASSWORD_ENCRYPTION_INITVECTOR + appendix, value)
}
fun getPasswordEncryptionInitVector(appendix: String): String {
return getString(PREFKEY_PASSWORD_ENCRYPTION_INITVECTOR + appendix, "")
}
fun setEncryptedPassword(appendix: String, value: String) {
setString(PREFKEY_ENCRYPTED_PASSWORD + appendix, value)
}
fun getEncryptedPassword(appendix: String): String {
return getString(PREFKEY_ENCRYPTED_PASSWORD + appendix, "")
}
fun setEncryptedPasswordDerivedKeyInitVector(appendix: String, value: String) {
setString(PREFKEY_ENCRYPTED_PASSWORD_DERIVED_KEY_INITVECTOR + appendix, value)
}
fun getBiometricsKeyEncryptionInitVector(appendix: String): String {
return getString(PREFKEY_ENCRYPTED_PASSWORD_DERIVED_KEY_INITVECTOR + appendix, "")
}
fun getAuthKeyName(): String {
return getString(PREFKEY_BIOMETRIC_KEY, "default_key")
}
fun setAuthKeyName(key: String) {
return setString(PREFKEY_BIOMETRIC_KEY, key)
}
fun getTermsHashed(): Int {
return getInt(PREFKEY_TERMS_HASHED, 0)
}
fun setTermsHashed(key: Int) {
return setInt(PREFKEY_TERMS_HASHED, key)
}
fun isShieldingEnabled(accountAddress: String): Boolean {
return getBoolean(PREFKEY_SHIELDING_ENABLED_ + accountAddress, false)
}
fun setShieldingEnabled(accountAddress: String, value: Boolean) {
return setBoolean(PREFKEY_SHIELDING_ENABLED_ + accountAddress, value)
}
fun setIdentityPendingWarningAcknowledged(id: Int) {
return setBoolean(PREFKEY_IDENTITY_PENDING_ACKNOWLEDGED + id, true)
}
fun isIdentityPendingWarningAcknowledged(id: Int): Boolean {
return getBoolean(PREFKEY_IDENTITY_PENDING_ACKNOWLEDGED + id, false)
}
suspend fun tryToSetEncryptedSeedPhrase(value: String, password: String): Boolean {
val seed = Mnemonics.MnemonicCode(value).toSeed()
val seedEncoded = seed.toHex()
val encryptedSeed =
App.appCore.getCurrentAuthenticationManager().encryptInBackground(password, seedEncoded)
?: return false
return setStringWithResult(SEED_PHRASE_ENCRYPTED, encryptedSeed)
}
suspend fun getSeedPhrase(password: String): String {
getString(SEED_PHRASE_ENCRYPTED)?.let { seedEncrypted ->
return App.appCore.getOriginalAuthenticationManager()
.decryptInBackground(password, seedEncrypted) ?: return ""
}
return ""
}
suspend fun getSeedPhrase(decryptKey: SecretKey): String? {
getString(SEED_PHRASE_ENCRYPTED)?.let { seedEncrypted ->
return App.appCore.getOriginalAuthenticationManager()
.decryptInBackground(decryptKey, seedEncrypted)
}
return null
}
/**
* Check if the old unencrypted seed is present
*
* If the old unencrypted seed is present, encrypt it, save the new encrypted seed.
*
* Then get the encrypted seed from SharedPreference, decrypt it and compare it to the unencrypted seed. If they match delete the old seed.
*
* @param password the password required to encrypt the seed
* @return Returns [Boolean]
*
* **true** if there is no unencrypted seed saved. This can happen when new user has setup password and biometrics and exited the app before saving the seed phrase.
* Next time when he starts the app he will be presented with the Authentication screen and after successful password the user needs to be able to continue with the seed-phrase setup.
*
* **true** if the seed is successfully encrypted, the encrypted seed is successfully saved,
* the decrypted and unencrypted seeds match and the old seed is successfully deleted.
*/
suspend fun checkAndTryToEncryptSeed(password: String): Boolean {
val seedUnencrypted = getString(SEED_PHRASE) ?: return true
//Unencrypted seed is present, encrypt it, save it and delete the old.
val encryptedSeed = App.appCore.getCurrentAuthenticationManager()
.encryptInBackground(password, seedUnencrypted) ?: return false
setStringWithResult(SEED_PHRASE_ENCRYPTED, encryptedSeed).let { saveSuccess ->
if (saveSuccess) {
val decryptedSeed = getSeedPhrase(password)
return decryptedSeed == seedUnencrypted && setStringWithResult(SEED_PHRASE, null)
}
}
return false
}
fun updateEncryptedSeedPhrase(encryptedSeed: String): Boolean {
return setStringWithResult(SEED_PHRASE_ENCRYPTED, encryptedSeed)
}
fun hasSeedPhrase(): Boolean {
return getString(SEED_PHRASE_ENCRYPTED) != null || getString(SEED_PHRASE) != null
}
}