Update: 2026-05-15 04:16:32

This commit is contained in:
Hamza-Ayed
2026-05-15 04:16:32 +03:00
parent 5b34f3ae07
commit fefe913ab7
7 changed files with 99 additions and 0 deletions

View File

@@ -17,6 +17,32 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 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 { buildTypes {
release { release {
isMinifyEnabled = true isMinifyEnabled = true
@@ -25,6 +51,7 @@ android {
getDefaultProguardFile("proguard-android-optimize.txt"), getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro" "proguard-rules.pro"
) )
signingConfig = signingConfigs.getByName("release")
} }
debug { debug {
isMinifyEnabled = false isMinifyEnabled = false

4
app/key.properties Normal file
View File

@@ -0,0 +1,4 @@
storePassword=21010333
keyPassword=21010333
keyAlias=sportnewskey
storeFile=/Users/hamzaaleghwairyeen/development/upload-keystore

View File

@@ -20,6 +20,8 @@ import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.jordanbot.autoride.service.BotForegroundService import com.jordanbot.autoride.service.BotForegroundService
import com.jordanbot.autoride.service.OverlayService import com.jordanbot.autoride.service.OverlayService
import com.jordanbot.autoride.api.ApiClient
import com.jordanbot.autoride.utils.DeviceUtils
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -51,6 +53,9 @@ class MainActivity : AppCompatActivity() {
// Load Settings // Load Settings
FilterEngine.init(this) FilterEngine.init(this)
// Set App Signature for API Security
ApiClient.appSignature = DeviceUtils.getAppSignatureSHA256(this)
// Load cached subscription data // Load cached subscription data
SubscriptionManager.loadLocalCache(this) SubscriptionManager.loadLocalCache(this)

View File

@@ -4,6 +4,8 @@ import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.POST import retrofit2.http.POST
import okhttp3.Interceptor
import okhttp3.OkHttpClient
// Data models for the API // Data models for the API
data class RideLogRequest( data class RideLogRequest(
@@ -78,10 +80,23 @@ interface BackendApiService {
object ApiClient { object ApiClient {
// Replace with your actual server URL // Replace with your actual server URL
private const val BASE_URL = "https://lawer.tripz-egypt.com/jordan_bot/backend/" 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 { val service: BackendApiService by lazy {
Retrofit.Builder() Retrofit.Builder()
.baseUrl(BASE_URL) .baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build() .build()
.create(BackendApiService::class.java) .create(BackendApiService::class.java)

View File

@@ -3,6 +3,9 @@ package com.jordanbot.autoride.utils
import android.content.Context import android.content.Context
import android.provider.Settings import android.provider.Settings
import android.content.pm.PackageManager
import java.security.MessageDigest
object DeviceUtils { object DeviceUtils {
/** /**
* Returns a unique fingerprint for the device based on Android ID. * Returns a unique fingerprint for the device based on Android ID.
@@ -10,4 +13,25 @@ object DeviceUtils {
fun getDeviceFingerprint(context: Context): String { fun getDeviceFingerprint(context: Context): String {
return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) ?: "UNKNOWN_DEVICE" 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 ""
}
} }

View File

@@ -39,6 +39,29 @@ if (!$envLoaded) {
exit; 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'; $host = $_ENV['DB_HOST'] ?? 'localhost';
$dbname = $_ENV['DB_NAME'] ?? 'jordan_bot_db'; $dbname = $_ENV['DB_NAME'] ?? 'jordan_bot_db';
$username = $_ENV['DB_USER'] ?? 'root'; $username = $_ENV['DB_USER'] ?? 'root';

View File

@@ -6,3 +6,4 @@
# header note. # header note.
#Thu May 14 16:37:36 EET 2026 #Thu May 14 16:37:36 EET 2026
sdk.dir=/Users/hamzaaleghwairyeen/Library/Android/sdk sdk.dir=/Users/hamzaaleghwairyeen/Library/Android/sdk
API_KEY="JB_8a7d6c5b4a39281706f5e4d3c2b1a0"