From fefe913ab7120ba71d36c03e923c1703e53b6ef3 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Fri, 15 May 2026 04:16:32 +0300 Subject: [PATCH] Update: 2026-05-15 04:16:32 --- app/build.gradle.kts | 27 +++++++++++++++++++ app/key.properties | 4 +++ .../com/jordanbot/autoride/MainActivity.kt | 5 ++++ .../com/jordanbot/autoride/api/BackendApi.kt | 15 +++++++++++ .../jordanbot/autoride/utils/DeviceUtils.kt | 24 +++++++++++++++++ backend/config/db.php | 23 ++++++++++++++++ local.properties | 1 + 7 files changed, 99 insertions(+) create mode 100644 app/key.properties diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 232fc3b..976531a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,6 +17,32 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } + val localProperties = java.util.Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { + localProperties.load(java.io.FileInputStream(localPropertiesFile)) + } + val apiKey = localProperties.getProperty("API_KEY", "\"\"") + + defaultConfig { + buildConfigField("String", "API_KEY", apiKey) + } + + val keystorePropertiesFile = rootProject.file("app/key.properties") + val keystoreProperties = java.util.Properties() + if (keystorePropertiesFile.exists()) { + keystoreProperties.load(java.io.FileInputStream(keystorePropertiesFile)) + } + + signingConfigs { + create("release") { + keyAlias = keystoreProperties["keyAlias"] as String? + keyPassword = keystoreProperties["keyPassword"] as String? + storeFile = keystoreProperties["storeFile"]?.let { file(it) } + storePassword = keystoreProperties["storePassword"] as String? + } + } + buildTypes { release { isMinifyEnabled = true @@ -25,6 +51,7 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) + signingConfig = signingConfigs.getByName("release") } debug { isMinifyEnabled = false diff --git a/app/key.properties b/app/key.properties new file mode 100644 index 0000000..20899db --- /dev/null +++ b/app/key.properties @@ -0,0 +1,4 @@ +storePassword=21010333 +keyPassword=21010333 +keyAlias=sportnewskey +storeFile=/Users/hamzaaleghwairyeen/development/upload-keystore diff --git a/app/src/main/java/com/jordanbot/autoride/MainActivity.kt b/app/src/main/java/com/jordanbot/autoride/MainActivity.kt index 9cf9308..85a0ed4 100644 --- a/app/src/main/java/com/jordanbot/autoride/MainActivity.kt +++ b/app/src/main/java/com/jordanbot/autoride/MainActivity.kt @@ -20,6 +20,8 @@ import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat import com.jordanbot.autoride.service.BotForegroundService import com.jordanbot.autoride.service.OverlayService +import com.jordanbot.autoride.api.ApiClient +import com.jordanbot.autoride.utils.DeviceUtils import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.launch @@ -51,6 +53,9 @@ class MainActivity : AppCompatActivity() { // Load Settings FilterEngine.init(this) + // Set App Signature for API Security + ApiClient.appSignature = DeviceUtils.getAppSignatureSHA256(this) + // Load cached subscription data SubscriptionManager.loadLocalCache(this) diff --git a/app/src/main/java/com/jordanbot/autoride/api/BackendApi.kt b/app/src/main/java/com/jordanbot/autoride/api/BackendApi.kt index 761b9f5..aa21d53 100644 --- a/app/src/main/java/com/jordanbot/autoride/api/BackendApi.kt +++ b/app/src/main/java/com/jordanbot/autoride/api/BackendApi.kt @@ -4,6 +4,8 @@ import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.Body import retrofit2.http.POST +import okhttp3.Interceptor +import okhttp3.OkHttpClient // Data models for the API data class RideLogRequest( @@ -78,10 +80,23 @@ interface BackendApiService { object ApiClient { // Replace with your actual server URL private const val BASE_URL = "https://lawer.tripz-egypt.com/jordan_bot/backend/" + private val API_KEY = com.jordanbot.autoride.BuildConfig.API_KEY + var appSignature: String = "" + + private val httpClient = OkHttpClient.Builder().apply { + addInterceptor(Interceptor { chain -> + val request = chain.request().newBuilder() + .addHeader("X-API-Key", API_KEY) + .addHeader("X-App-Signature", appSignature) + .build() + chain.proceed(request) + }) + }.build() val service: BackendApiService by lazy { Retrofit.Builder() .baseUrl(BASE_URL) + .client(httpClient) .addConverterFactory(GsonConverterFactory.create()) .build() .create(BackendApiService::class.java) diff --git a/app/src/main/java/com/jordanbot/autoride/utils/DeviceUtils.kt b/app/src/main/java/com/jordanbot/autoride/utils/DeviceUtils.kt index 6371fc0..8d3834f 100644 --- a/app/src/main/java/com/jordanbot/autoride/utils/DeviceUtils.kt +++ b/app/src/main/java/com/jordanbot/autoride/utils/DeviceUtils.kt @@ -3,6 +3,9 @@ package com.jordanbot.autoride.utils import android.content.Context import android.provider.Settings +import android.content.pm.PackageManager +import java.security.MessageDigest + object DeviceUtils { /** * Returns a unique fingerprint for the device based on Android ID. @@ -10,4 +13,25 @@ object DeviceUtils { fun getDeviceFingerprint(context: Context): String { return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) ?: "UNKNOWN_DEVICE" } + + /** + * Returns the SHA-256 signature of the installed app. + */ + fun getAppSignatureSHA256(context: Context): String { + try { + val packageInfo = context.packageManager.getPackageInfo( + context.packageName, + PackageManager.GET_SIGNATURES + ) + for (signature in packageInfo.signatures) { + val md = MessageDigest.getInstance("SHA-256") + md.update(signature.toByteArray()) + val digest = md.digest() + return digest.joinToString("") { "%02x".format(it) } + } + } catch (e: Exception) { + e.printStackTrace() + } + return "" + } } diff --git a/backend/config/db.php b/backend/config/db.php index 2901cff..cfd802a 100644 --- a/backend/config/db.php +++ b/backend/config/db.php @@ -39,6 +39,29 @@ if (!$envLoaded) { exit; } +// Security: API Key Validation +$expectedApiKey = $_ENV['API_KEY'] ?? 'JORDAN_BOT_SECRET_2026'; // Fallback if not in .env +$headers = getallheaders(); +$providedKey = $headers['X-API-Key'] ?? ($headers['x-api-key'] ?? null); + +if ($providedKey !== $expectedApiKey) { + http_response_code(401); + echo json_encode(['success' => false, 'message' => 'Unauthorized: Invalid or missing API Key']); + exit; +} + +// Extra Security: App Signature Fingerprint Validation (Optional) +$expectedAppSignature = $_ENV['APP_SIGNATURE_SHA256'] ?? null; +if (!empty($expectedAppSignature)) { + $providedSignature = $headers['X-App-Signature'] ?? ($headers['x-app-signature'] ?? null); + // Ignore case and compare + if (strcasecmp($providedSignature, $expectedAppSignature) !== 0) { + http_response_code(403); + echo json_encode(['success' => false, 'message' => 'Forbidden: Invalid App Signature (Anti-Tamper)']); + exit; + } +} + $host = $_ENV['DB_HOST'] ?? 'localhost'; $dbname = $_ENV['DB_NAME'] ?? 'jordan_bot_db'; $username = $_ENV['DB_USER'] ?? 'root'; diff --git a/local.properties b/local.properties index bc6cf66..fd99e45 100644 --- a/local.properties +++ b/local.properties @@ -6,3 +6,4 @@ # header note. #Thu May 14 16:37:36 EET 2026 sdk.dir=/Users/hamzaaleghwairyeen/Library/Android/sdk +API_KEY="JB_8a7d6c5b4a39281706f5e4d3c2b1a0"