Skip to content

Commit

Permalink
5.0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
polstianka committed Nov 4, 2024
1 parent cd29cbd commit 4738c38
Show file tree
Hide file tree
Showing 17 changed files with 119 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ fun <R> withRetry(
return null
} catch (e: Throwable) {
val statusCode = e.getHttpStatusCode()
if (statusCode == 429) {
if (statusCode == 429 || statusCode == 401 || statusCode == 502) {
SystemClock.sleep(delay)
continue
}
if (statusCode >= 500 || statusCode == 404) {
if (statusCode >= 500 || statusCode == 404 || statusCode == 400) {
return null
}
FirebaseCrashlytics.getInstance().recordException(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ class AccountRepository(
return vaultSource.getMnemonic(wallet.publicKey)
}

suspend fun getPrivateKey(id: String): PrivateKeyEd25519 {
val wallet = database.getAccount(id) ?: return EmptyPrivateKeyEd25519.invoke()
return vaultSource.getPrivateKey(wallet.publicKey) ?: EmptyPrivateKeyEd25519.invoke()
suspend fun getPrivateKey(id: String): PrivateKeyEd25519? {
val wallet = database.getAccount(id) ?: return null
return vaultSource.getPrivateKey(wallet.publicKey)
}

suspend fun pairLedger(
Expand Down Expand Up @@ -367,7 +367,7 @@ class AccountRepository(
}
}

private fun createTonProofToken(wallet: WalletEntity): String? {
private suspend fun createTonProofToken(wallet: WalletEntity): String? {
val payload = api.tonconnectPayload() ?: return null
return try {
val publicKey = wallet.publicKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import com.tonapps.extensions.getByteArray
import com.tonapps.extensions.putByteArray
import com.tonapps.security.Security
import com.tonapps.security.clear
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.ton.api.pk.PrivateKeyEd25519
import org.ton.api.pub.PublicKeyEd25519
import org.ton.mnemonic.Mnemonic
Expand Down Expand Up @@ -47,8 +49,25 @@ internal class VaultSource(context: Context) {
return publicKey
}

fun getPrivateKey(publicKey: PublicKeyEd25519): PrivateKeyEd25519? {
return prefs.getPrivateKey(privateKey(publicKey))
suspend fun getPrivateKey(publicKey: PublicKeyEd25519): PrivateKeyEd25519? = withContext(Dispatchers.IO) {
val privateKey = prefs.getPrivateKey(privateKey(publicKey))
if (privateKey == null) {
val fromMnemonic = getPrivateKeyFromMnemonic(publicKey) ?: return@withContext null
prefs.edit {
putByteArray(privateKey(publicKey), fromMnemonic.key.toByteArray())
}
fromMnemonic
} else {
privateKey
}
}

private fun getPrivateKeyFromMnemonic(publicKey: PublicKeyEd25519): PrivateKeyEd25519? {
val mnemonic = getMnemonic(publicKey) ?: return null
val seed = Mnemonic.toSeed(mnemonic.toList())
val privateKey = PrivateKeyEd25519(seed)
seed.clear()
return privateKey
}

private fun privateKey(publicKey: PublicKeyEd25519) = key(PRIVATE_KEY_PREFIX, publicKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class ScreenCacheSource(
): ByteArray {
try {
val file = getFile(name, walletId)
if (!file.exists() || file.length() == 0L) {
throw IllegalStateException("File not found: ${file.absolutePath}")
if (!file.exists() || file.length() == 0L || !file.canRead()) {
return byteArrayOf()
}
return file.readBytes()
} catch (e: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class PasscodeManager(
rnLegacy.hasPinCode()
}
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
false
}
}
Expand Down Expand Up @@ -185,12 +186,29 @@ class PasscodeManager(
private suspend fun confirmationMigration(
context: Context,
): Boolean = withContext(Dispatchers.Main) {
try {
val passcode = if (settingsRepository.biometric) {
val passcodeByBiometric: String? = try {
if (settingsRepository.biometric) {
rnLegacy.exportPasscodeWithBiometry()
} else {
null
}
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
null
}

val passcodeByDialog: String? = try {
if (passcodeByBiometric.isNullOrEmpty()) {
PasscodeDialog.request(context)
} else {
null
}
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
null
}
try {
val passcode = passcodeByBiometric ?: passcodeByDialog
if (passcode.isNullOrBlank()) {
throw Exception("failed to request passcode")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ internal class SecureStoreModule(
return keyStoreEntryClass.cast(entry)
}

private fun <E : KeyStore.Entry> getKeyEntry(
private suspend fun <E : KeyStore.Entry> getKeyEntry(
keyStoreEntryClass: Class<E>,
encryptor: KeyBasedEncryptor<E>,
options: SecureStoreOptions,
Expand All @@ -273,7 +273,7 @@ internal class SecureStoreModule(
return keyStoreEntry
}

private fun <E : KeyStore.Entry> getPreferredKeyEntry(
private suspend fun <E : KeyStore.Entry> getPreferredKeyEntry(
keyStoreEntryClass: Class<E>,
encryptor: KeyBasedEncryptor<E>,
options: SecureStoreOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class HistoryHelper(
}
it
}.map { wallet ->
val privateKey = accountRepository.getPrivateKey(wallet.id)
val privateKey = accountRepository.getPrivateKey(wallet.id) ?: throw Exception("Private key not found")
val decrypted = CommentEncryption.decryptComment(
wallet.publicKey,
privateKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class MainRecyclerView @JvmOverloads constructor(
}

override fun dispatchDraw(canvas: Canvas) {
if (topBlur == null) {
if (topBlur == null || !topBlur.hasBlur) {
super.dispatchDraw(canvas)
} else {
topBlur.draw(canvas) {
Expand All @@ -76,7 +76,7 @@ class MainRecyclerView @JvmOverloads constructor(
}

override fun draw(canvas: Canvas) {
if (bottomBlur == null) {
if (bottomBlur == null || !bottomBlur.hasBlur) {
super.draw(canvas)
} else {
bottomBlur.draw(canvas) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.tonapps.tonkeeper.ui.screen.send.main

import android.app.Application
import android.util.Log
import androidx.lifecycle.viewModelScope
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tonapps.blockchain.ton.contract.WalletFeature
Expand Down Expand Up @@ -939,7 +940,7 @@ class SendViewModel(
_uiEventFlow.tryEmit(SendEvent.Loading)
Triple(boc, transfer.wallet, internalMessage)
}.catch {
FirebaseCrashlytics.getInstance().recordException(it)
FirebaseCrashlytics.getInstance().recordException(Throwable("SendViewModel sign failed", it))
if (it !is CancellationException) {
_uiEventFlow.tryEmit(SendEvent.Failed(it))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,11 @@ class SignProof(
throw CancellationException("Passcode cancelled")
}

val privateKey = accountRepository.getPrivateKey(wallet.id) ?: throw Throwable("Private key not found")

return TONProof.sign(
address = wallet.contract.address,
secretKey = accountRepository.getPrivateKey(wallet.id),
secretKey = privateKey,
payload = payload,
domain = domain
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tonapps.tonkeeper.usecase.sign

import android.util.Log
import com.tonapps.blockchain.ton.extensions.EmptyPrivateKeyEd25519.sign
import com.tonapps.blockchain.ton.extensions.hex
import com.tonapps.ledger.ton.Transaction
Expand Down Expand Up @@ -111,7 +112,7 @@ class SignTransaction(
if (!isValidPasscode) {
throw SendException.WrongPasscode()
}
val privateKey = accountRepository.getPrivateKey(wallet.id)
val privateKey = accountRepository.getPrivateKey(wallet.id) ?: throw SendException.UnableSendTransaction()
val hash = privateKey.sign(unsignedBody.hash())
BitString(hash)
}
Expand Down
2 changes: 1 addition & 1 deletion apps/wallet/instance/main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ android {
targetSdk = 34
versionCode = 600

versionName = "5.0.8" // Format is "major.minor.patch" (e.g. "1.0.0") and only numbers are allowed
versionName = "5.0.9" // Format is "major.minor.patch" (e.g. "1.0.0") and only numbers are allowed

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
3 changes: 3 additions & 0 deletions lib/blockchain/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ android {
}

dependencies {
api(platform(Dependence.Firebase.bom))
api(Dependence.Firebase.crashlytics)

api(Dependence.TON.tvm)
api(Dependence.TON.crypto)
api(Dependence.TON.tlb)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,45 @@ package com.tonapps.blockchain.ton.extensions

import android.content.SharedPreferences
import android.util.Base64
import android.util.Log
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tonapps.base64.decodeBase64
import io.ktor.util.decodeBase64Bytes
import org.ton.api.pk.PrivateKeyEd25519

fun SharedPreferences.getPrivateKey(key: String): PrivateKeyEd25519? {
return getPrivateKey2(key) ?: getPrivateKey1(key)
val base64 = getString(key, null)
if (base64.isNullOrEmpty()) {
return null
}
return decodePrivateKey2(key) ?: decodePrivateKey1(key) ?: decodePrivateKey3(key)
}

private fun SharedPreferences.getPrivateKey1(key: String): PrivateKeyEd25519? {
// Bad hack to decode private key....

private fun decodePrivateKey1(base64: String): PrivateKeyEd25519? {
try {
val base64 = getString(key, null)
if (base64.isNullOrEmpty()) {
return null
}
return PrivateKeyEd25519(base64.decodeBase64())
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
return null
}
}

private fun SharedPreferences.getPrivateKey2(key: String): PrivateKeyEd25519? {
private fun decodePrivateKey2(base64: String): PrivateKeyEd25519? {
try {
val base64 = getString(key, null)
if (base64.isNullOrEmpty()) {
return null
}
return PrivateKeyEd25519(Base64.decode(base64, Base64.DEFAULT))
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
return null
}
}

private fun decodePrivateKey3(base64: String): PrivateKeyEd25519? {
try {
return PrivateKeyEd25519(base64.decodeBase64Bytes())
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
return null
}
}
3 changes: 3 additions & 0 deletions lib/security/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ android {
}

dependencies {
api(platform(Dependence.Firebase.bom))
api(Dependence.Firebase.crashlytics)

implementation(Dependence.KotlinX.coroutines)
implementation(Dependence.AndroidX.security)
implementation(project(Dependence.Lib.extensions))
Expand Down
39 changes: 27 additions & 12 deletions lib/security/src/main/java/com/tonapps/security/Security.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tonapps.security

import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
Expand All @@ -10,6 +11,7 @@ import android.os.Build
import android.provider.Settings
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.security.keystore.UserNotAuthenticatedException
import android.util.Log
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
Expand Down Expand Up @@ -42,18 +44,31 @@ object Security {

@Synchronized
fun pref(context: Context, keyAlias: String, name: String): SharedPreferences {
Log.d("SecurityPrefLog", "pref: $keyAlias")
KeyHelper.createIfNotExists(keyAlias)

return EncryptedSharedPreferences.create(
name,
keyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

// UserNotAuthenticatedException
try {
KeyHelper.createIfNotExists(keyAlias)

return EncryptedSharedPreferences.create(
name,
keyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
} catch (e: UserNotAuthenticatedException) {
openUserAuthentication(context)
throw e
} catch (e: Throwable) {
throw e
}
}

private fun openUserAuthentication(context: Context) {
try {
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val intent = keyguardManager.createConfirmDeviceCredentialIntent("Tonkeeper", "Auth") ?: return
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
} catch (ignored: Throwable) { }
}

fun generatePrivateKey(keySize: Int): SecretKey {
Expand Down
1 change: 1 addition & 0 deletions ui/blur/src/main/java/blur/BlurCompat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.RectF
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import blur.node.api31.BlurNode
import blur.node.api31.ContentNode
Expand Down

0 comments on commit 4738c38

Please sign in to comment.