Skip to content

Commit

Permalink
single base64 implementation for all app parts
Browse files Browse the repository at this point in the history
  • Loading branch information
polstianka committed Oct 20, 2024
1 parent 1f99225 commit 9b41b21
Show file tree
Hide file tree
Showing 33 changed files with 347 additions and 116 deletions.
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 0 additions & 5 deletions apps/signer/src/main/java/com/tonapps/signer/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ import androidx.camera.core.CameraXConfig
import com.tonapps.signer.screen.crash.CrashActivity
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
import org.ton.crypto.base64
import com.tonapps.security.Security
import java.io.PrintWriter
import java.io.StringWriter


class App: Application(), CameraXConfig.Provider {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.tonapps.signer.screen.sign

import android.os.Bundle
import android.util.Log
import com.tonapps.blockchain.ton.TonNetwork
import com.tonapps.blockchain.ton.extensions.base64
import com.tonapps.blockchain.ton.extensions.hex
import com.tonapps.blockchain.ton.extensions.parseCell
import com.tonapps.signer.Key
Expand Down
8 changes: 0 additions & 8 deletions apps/wallet/api/src/main/java/com/tonapps/wallet/api/API.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ import com.tonapps.blockchain.ton.contract.BaseWalletContract
import com.tonapps.blockchain.ton.contract.WalletVersion
import com.tonapps.blockchain.ton.extensions.EmptyPrivateKeyEd25519
import com.tonapps.blockchain.ton.extensions.base64
import com.tonapps.blockchain.ton.extensions.equalsAddress
import com.tonapps.blockchain.ton.extensions.isValidTonAddress
import com.tonapps.blockchain.ton.extensions.toAccountId
import com.tonapps.blockchain.ton.extensions.toRawAddress
import com.tonapps.extensions.bestMessage
import com.tonapps.extensions.locale
import com.tonapps.extensions.toUriOrNull
import com.tonapps.extensions.unicodeToPunycode
Expand All @@ -27,7 +24,6 @@ import com.tonapps.network.interceptor.AcceptLanguageInterceptor
import com.tonapps.network.interceptor.AuthorizationInterceptor
import com.tonapps.network.post
import com.tonapps.network.postJSON
import com.tonapps.network.simple
import com.tonapps.network.sse
import com.tonapps.wallet.api.core.SourceAPI
import com.tonapps.wallet.api.entity.AccountDetailsEntity
Expand All @@ -42,7 +38,6 @@ import io.batteryapi.apis.BatteryApi
import io.batteryapi.apis.BatteryApi.UnitsGetBalance
import io.batteryapi.models.Balance
import io.batteryapi.models.Config
import io.batteryapi.models.PromoCodeBatteryPurchaseRequest
import io.batteryapi.models.RechargeMethods
import io.tonapi.infrastructure.ClientException
import io.tonapi.infrastructure.Serializer
Expand All @@ -57,7 +52,6 @@ import io.tonapi.models.MessageConsequences
import io.tonapi.models.NftItem
import io.tonapi.models.SendBlockchainMessageRequest
import io.tonapi.models.TokenRates
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -66,7 +60,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
Expand All @@ -75,7 +68,6 @@ import okhttp3.Response
import org.json.JSONArray
import org.json.JSONObject
import org.ton.api.pub.PublicKeyEd25519
import org.ton.block.AddrStd
import org.ton.cell.Cell
import org.ton.crypto.hex
import java.util.Locale
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import android.content.Context
import androidx.core.content.edit
import com.tonapps.blockchain.ton.extensions.hex
import com.tonapps.extensions.getByteArray
import com.tonapps.extensions.putByteArray
import com.tonapps.security.Security
import com.tonapps.security.clear
import com.tonapps.security.putByteArray
import org.ton.api.pk.PrivateKeyEd25519
import org.ton.api.pub.PublicKeyEd25519
import org.ton.mnemonic.Mnemonic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ data class RawMessageEntity(
parseAmount(json.get("amount")),
json.optString("stateInit"),
json.optString("payload")
) {
/*if (payload.base64() != payloadValue) {
throw IllegalStateException("Payload is not equal")
}*/
}
)

private companion object {

Expand Down
1 change: 1 addition & 0 deletions apps/wallet/data/dapps/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ dependencies {
implementation(project(Dependence.Lib.sqlite))
implementation(project(Dependence.Lib.security))
implementation(project(Dependence.Lib.network))
implementation(project(Dependence.Lib.base64))
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.tonapps.wallet.data.dapps.entities

import android.net.Uri
import com.tonapps.extensions.base64
import android.util.Base64
import android.util.Log
import com.tonapps.base64.decodeBase64
import com.tonapps.security.CryptoBox
import com.tonapps.security.Sodium
import com.tonapps.security.hex
Expand Down Expand Up @@ -31,6 +33,9 @@ data class AppConnectEntity(
localPrivateKey: ByteArray,
body: ByteArray
): ByteArray {
Log.d("AppConnectEntityLog", "encryptMessage: remotePublicKey = ${remotePublicKey.joinToString()}")
Log.d("AppConnectEntityLog", "encryptMessage: localPrivateKey = ${localPrivateKey.joinToString()}")
Log.d("AppConnectEntityLog", "encryptMessage: body = ${body.toString(Charsets.UTF_8)}")
val nonce = CryptoBox.nonce()
val cipher = ByteArray(body.size + Sodium.cryptoBoxMacBytes())
Sodium.cryptoBoxEasy(cipher, body, body.size, nonce, remotePublicKey, localPrivateKey)
Expand All @@ -43,8 +48,11 @@ data class AppConnectEntity(
body: ByteArray
): ByteArray {
val nonce = body.sliceArray(0 until Sodium.cryptoBoxNonceBytes())
Log.d("AppConnectEntityLog", "nonce = ${nonce.joinToString()}")
val cipher = body.sliceArray(Sodium.cryptoBoxNonceBytes() until body.size)
Log.d("AppConnectEntityLog", "cipher = ${cipher.joinToString()}")
val message = ByteArray(cipher.size - Sodium.cryptoBoxMacBytes())
Log.d("AppConnectEntityLog", "message = ${message.joinToString()}")
Sodium.cryptoBoxOpenEasy(message, cipher, cipher.size, nonce, remotePublicKey, localPrivateKey)
return message
}
Expand All @@ -54,17 +62,21 @@ data class AppConnectEntity(
hex(keyPair.publicKey)
}

fun encryptMessage(body: ByteArray): ByteArray {
return encryptMessage(clientId.hex(), keyPair.privateKey, body)
}

fun decryptMessage(body: ByteArray): ByteArray {
return decryptMessage(clientId.hex(), keyPair.privateKey, body)
}

fun decryptEventMessage(message: String): JSONObject {
val bytes = message.base64
val decrypted = decryptMessage(bytes)
return JSONObject(decrypted.toString(Charsets.UTF_8))
fun decryptEventMessage(message: String): JSONObject? {
try {
Log.d("AppConnectEntityLog", "decryptEventMessage: message = \"$message\"")
val bytes = message.decodeBase64()
Log.d("AppConnectEntityLog", "decryptEventMessage: bytes = ${bytes.joinToString()}")
val decrypted = decryptMessage(bytes)
Log.d("AppConnectEntityLog", "decryptEventMessage: decrypted = ${decrypted.joinToString()}")
return JSONObject(decrypted.toString(Charsets.UTF_8))
} catch (e: Throwable) {
Log.e("AppConnectEntityLog", "decryptEventMessage: ", e)
return null
}
}
}
1 change: 1 addition & 0 deletions apps/wallet/instance/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ dependencies {
implementation(project(Dependence.Lib.extensions))
implementation(project(Dependence.Lib.ledger))
implementation(project(Dependence.Lib.ur))
implementation(project(Dependence.Lib.base64))

implementation(Dependence.AndroidX.Camera.base)
implementation(Dependence.AndroidX.Camera.core)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ class TonConnectManager(
} catch (e: ManifestException) {
JsonBuilder.connectEventError(BridgeError.resolve(e))
} catch (e: Throwable) {
Log.e("AppConnectEntityLog", "Error TONConnect", e)
JsonBuilder.connectEventError(BridgeError.UNKNOWN)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.tonapps.tonkeeper.manager.tonconnect.bridge

import android.util.Log
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tonapps.extensions.base64
import com.tonapps.base64.encodeBase64
import com.tonapps.extensions.optStringCompat
import com.tonapps.security.CryptoBox
import com.tonapps.security.hex
Expand All @@ -11,6 +12,7 @@ import com.tonapps.wallet.api.API
import com.tonapps.wallet.data.dapps.entities.AppConnectEntity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.withContext

Expand Down Expand Up @@ -69,7 +71,7 @@ internal class Bridge(private val api: API) {
): Boolean = withContext(Dispatchers.IO) {
try {
val encryptedMessage = AppConnectEntity.encryptMessage(clientId.hex(), keyPair.privateKey, unencryptedMessage.toByteArray())
api.tonconnectSend(hex(keyPair.publicKey), clientId, encryptedMessage.base64)
api.tonconnectSend(hex(keyPair.publicKey), clientId, encryptedMessage.encodeBase64())
true
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
Expand All @@ -88,12 +90,16 @@ internal class Bridge(private val api: API) {
val from = event.json.optStringCompat("from") ?: return@mapNotNull null
val message = event.json.optStringCompat("message") ?: return@mapNotNull null
val connection = connections.find { it.clientId == from } ?: return@mapNotNull null
val decryptedMessage = BridgeEvent.Message(connection.decryptEventMessage(message))
val json = connection.decryptEventMessage(message) ?: return@mapNotNull null
val decryptedMessage = BridgeEvent.Message(json)
BridgeEvent(
eventId = id,
message = decryptedMessage,
connection = connection.copy(),
)
}.catch {
Log.e("AppConnectEntityLog", "eventsFlow: ", it)
FirebaseCrashlytics.getInstance().recordException(it)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="@dimen/offsetMedium"
android:clipToPadding="false"/>

<!--android:topOffset="112dp" -->
android:clipToPadding="false"
android:topOffset="112dp"/>

</com.tonapps.tonkeeper.ui.component.MainSwipeRefreshLayout>

Expand Down Expand Up @@ -44,7 +43,6 @@
android:id="@+id/filters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:paddingBottom="16dp"
android:paddingHorizontal="@dimen/offsetMedium"/>

Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/Dependence.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ object Dependence {
const val sqlite = ":lib:sqlite"
const val ledger = ":lib:ledger"
const val ur = ":lib:ur"
const val base64 = ":lib:base64"
}

object UIKit {
Expand Down
1 change: 1 addition & 0 deletions lib/base64/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
23 changes: 23 additions & 0 deletions lib/base64/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}

android {
namespace = Build.namespacePrefix("base64")
compileSdk = Build.compileSdkVersion

defaultConfig {
minSdk = Build.minSdkVersion
consumerProguardFiles("consumer-rules.pro")
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = "1.8"
}
}
2 changes: 2 additions & 0 deletions lib/base64/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest/>
56 changes: 56 additions & 0 deletions lib/base64/src/main/java/com/tonapps/base64/Base64.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2022 Sascha Peilicke <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tonapps.base64

/**
* Encode a [String] to Base64 standard encoded [String].
*
* See [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
*/
val String.base64Encoded: String
get() = encodeInternal(Encoding.Standard)

/**
* Encode a [ByteArray] to Base64 standard encoded [String].
*
* See [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
*/
val ByteArray.base64Encoded: String
get() = asCharArray().concatToString().base64Encoded

/**
* Decode a Base64 standard encoded [String] to [String].
*
* See [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
*/
val String.base64Decoded: String
get() = decodeInternal(Encoding.Standard).map { it.toChar() }.joinToString("").dropLast(count { it == '=' })

/**
* Decode a Base64 standard encoded [String] to [ByteArray].
*
* See [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
*/
val String.base64DecodedBytes: ByteArray
get() = decodeInternal(Encoding.Standard).map { it.toByte() }.toList().dropLast(count { it == '=' }).toByteArray()

/**
* Decode a Base64 standard encoded [ByteArray] to [String].
*
* See [RFC 4648 §4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
*/
val ByteArray.base64Decoded: String
get() = asCharArray().concatToString().base64Decoded
Loading

0 comments on commit 9b41b21

Please sign in to comment.