diff --git a/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/Base58.kt b/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/Base58.kt new file mode 100644 index 0000000000..f286c9f383 --- /dev/null +++ b/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/Base58.kt @@ -0,0 +1,45 @@ +package net.nymtech.vpn.util + +import java.math.BigInteger + +object Base58 { + private const val ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + private val INDEXES = IntArray(128) { -1 }.also { + for (i in ALPHABET.indices) { + it[ALPHABET[i].code] = i + } + } + + fun isValidBase58(input: String, expectedByteLength: Int = 32): Boolean { + try { + if (input.isEmpty() || input.any { it.code >= 128 || INDEXES[it.code] == -1 }) { + return false + } + + val bytes = decode(input) + + return bytes.size == expectedByteLength + } catch (e: Exception) { + return false + } + } + + private fun decode(input: String): ByteArray { + if (input.isEmpty()) return ByteArray(0) + + val bigInt = input.fold(BigInteger.ZERO) { acc, char -> + val index = INDEXES[char.code] + if (index == -1) throw IllegalArgumentException("Invalid Base58 character: $char") + acc.multiply(BigInteger.valueOf(58)).add(BigInteger.valueOf(index.toLong())) + } + + val bytes = bigInt.toByteArray() + + val leadingZeros = input.takeWhile { it == '1' }.length + return if (bytes[0].toInt() == 0 && bytes.size > 1) { + ByteArray(leadingZeros) + bytes.drop(1).toByteArray() + } else { + ByteArray(leadingZeros) + bytes + } + } +} diff --git a/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/NotificationManager.kt b/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/NotificationManager.kt index 83747865ae..54b63d3372 100644 --- a/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/NotificationManager.kt +++ b/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/NotificationManager.kt @@ -20,7 +20,7 @@ internal class NotificationManager private constructor(val context: Context) { private const val VPN_CHANNEL_ID = "VpnForegroundChannel" } - fun createNotificationChannel() { + private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Create the NotificationChannel. val name = context.getString(R.string.channel_name) diff --git a/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/extensions/LibExtensions.kt b/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/extensions/LibExtensions.kt index 6072bf62f0..aa413b888e 100644 --- a/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/extensions/LibExtensions.kt +++ b/nym-vpn-android/core/src/main/java/net/nymtech/vpn/util/extensions/LibExtensions.kt @@ -1,6 +1,7 @@ package net.nymtech.vpn.util.extensions import net.nymtech.vpn.backend.Tunnel +import net.nymtech.vpn.util.Base58 import nym_vpn_lib.EntryPoint import nym_vpn_lib.ExitPoint import nym_vpn_lib.TunnelEvent @@ -39,16 +40,16 @@ fun String.asEntryPoint(): EntryPoint { this == "random" -> EntryPoint.Random this == "randomlowlatency" -> EntryPoint.RandomLowLatency length == 2 -> EntryPoint.Location(this.uppercase()) - length == 44 || length == 43 -> EntryPoint.Gateway(this) + Base58.isValidBase58(this, 32) -> EntryPoint.Gateway(this) else -> EntryPoint.Random } } fun String.asExitPoint(): ExitPoint { - return when (this.length) { - 2 -> ExitPoint.Location(this.uppercase()) - 134 -> ExitPoint.Address(this) - 44, 43 -> ExitPoint.Gateway(this) + return when { + length == 2 -> ExitPoint.Location(this.uppercase()) + length == 134 -> ExitPoint.Address(this) + Base58.isValidBase58(this, 32) -> ExitPoint.Gateway(this) else -> throw IllegalArgumentException("Invalid exit id") } }