Skip to content

Commit 78eb360

Browse files
authored
feat: password protection & hardware security & app signature added
* chore: ktlint Signed-off-by: Denis Dobanda <[email protected]> * feat: password protection check added Signed-off-by: Denis Dobanda <[email protected]> * feat: password protection check added Signed-off-by: Denis Dobanda <[email protected]> * feat: app signature missmatch detection added Signed-off-by: Denis Dobanda <[email protected]> --------- Signed-off-by: Denis Dobanda <[email protected]>
1 parent ee51856 commit 78eb360

File tree

23 files changed

+407
-125
lines changed

23 files changed

+407
-125
lines changed

.editorconfig

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
root = true
2+
3+
[*]
4+
insert_final_newline = true
5+
6+
[{*.kt,*.kts}]
7+
ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
8+
ktlint_code_style = android_studio
9+
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = 3
10+
max_line_length = 80
11+
12+
ktlint_function_naming_ignore_when_annotated_with = Composable
13+
14+
ij_kotlin_allow_trailing_comma = true
15+
ij_kotlin_allow_trailing_comma_on_call_site = true
16+
17+
# Disable wildcard imports entirely with the following three configurations
18+
ij_kotlin_name_count_to_use_star_import = 2147483647
19+
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
20+
ij_kotlin_packages_to_use_import_on_demand = unset

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ Already implemented Features are:
2020
- [x] Jailbreak or Root Detection
2121
- [x] Hooks Detection
2222
- [x] Simulator Detection
23+
- [x] Device Passcode Check
24+
- [x] Hardware Security Check
25+
- [x] App Signature Check
2326

2427
You can see them in action with the [Example App](./example)
2528
we've provided
@@ -99,11 +102,8 @@ reportedThreats.contains(ThreatDetectionCenter.Threat.SIMULATOR)
99102

100103
Next features to be implemented:
101104

102-
- [ ] App Signature Check
103105
- [ ] Debugger Detection
104-
- [ ] Device Passcode Check
105106
- [ ] Integrity Check
106-
- [ ] Hardware Security Check
107107

108108
## Contributing
109109

example/app/build.gradle.kts

+5-8
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,15 @@ android {
2525
isMinifyEnabled = false
2626
proguardFiles(
2727
getDefaultProguardFile("proguard-android-optimize.txt"),
28-
"proguard-rules.pro"
28+
"proguard-rules.pro",
2929
)
30-
// Don't do this, just just to test
30+
// Don't do this, just to test
3131
signingConfig = signingConfigs.getByName("debug")
3232
}
3333
}
3434
compileOptions {
35-
sourceCompatibility = JavaVersion.VERSION_1_8
36-
targetCompatibility = JavaVersion.VERSION_1_8
37-
}
38-
kotlinOptions {
39-
jvmTarget = "1.8"
35+
sourceCompatibility = JavaVersion.VERSION_21
36+
targetCompatibility = JavaVersion.VERSION_21
4037
}
4138
buildFeatures {
4239
compose = true
@@ -70,4 +67,4 @@ dependencies {
7067
androidTestImplementation(libs.androidx.ui.test.junit4)
7168
debugImplementation(libs.androidx.ui.tooling)
7269
debugImplementation(libs.androidx.ui.test.manifest)
73-
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package com.exxeta.mobilesecuritytoolkitexample
22

3-
import androidx.test.platform.app.InstrumentationRegistry
43
import androidx.test.ext.junit.runners.AndroidJUnit4
5-
4+
import androidx.test.platform.app.InstrumentationRegistry
5+
import org.junit.Assert.*
66
import org.junit.Test
77
import org.junit.runner.RunWith
88

9-
import org.junit.Assert.*
10-
119
/**
1210
* Instrumented test, which will execute on an Android device.
1311
*
@@ -19,6 +17,9 @@ class ExampleInstrumentedTest {
1917
fun useAppContext() {
2018
// Context of the app under test.
2119
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22-
assertEquals("com.exxeta.mobilesecuritytoolkitexample", appContext.packageName)
20+
assertEquals(
21+
"com.exxeta.mobilesecuritytoolkitexample",
22+
appContext.packageName,
23+
)
2324
}
24-
}
25+
}

example/app/src/main/java/com/exxeta/mobilesecuritytoolkitexample/MainActivity.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.os.Bundle
44
import androidx.activity.ComponentActivity
55
import androidx.activity.compose.setContent
66
import androidx.activity.enableEdgeToEdge
7-
import androidx.compose.ui.platform.LocalContext
87
import com.exxeta.mobilesecuritytoolkitexample.ui.theme.MobileSecurityToolkitExampleTheme
98

109
class MainActivity : ComponentActivity() {
@@ -17,4 +16,4 @@ class MainActivity : ComponentActivity() {
1716
}
1817
}
1918
}
20-
}
19+
}

example/app/src/main/java/com/exxeta/mobilesecuritytoolkitexample/ThreatStatusList.kt

+28-8
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import com.exxeta.securitytoolkit.ThreatDetectionCenter
2828

2929
@Composable
3030
fun ThreatStatusList() {
31-
3231
val context = LocalContext.current
3332
val detectionCenter = ThreatDetectionCenter(context)
3433
detectionCenter.threats
@@ -46,7 +45,9 @@ fun ThreatStatusList() {
4645
ThreatStatus(
4746
"Root",
4847
"Is a way of acquiring privileged control over the operating system of a device. Tools such as Magisk or Shadow can hide the privileged access",
49-
reportedThreats.contains(ThreatDetectionCenter.Threat.ROOT_PRIVILEGES),
48+
reportedThreats.contains(
49+
ThreatDetectionCenter.Threat.ROOT_PRIVILEGES,
50+
),
5051
),
5152
ThreatStatus(
5253
"Hooks",
@@ -58,11 +59,30 @@ fun ThreatStatusList() {
5859
"Running the application in an Emulator",
5960
reportedThreats.contains(ThreatDetectionCenter.Threat.SIMULATOR),
6061
),
62+
ThreatStatus(
63+
"Passcode",
64+
"Indicates if current device is unprotected with a passcode. Biometric protection requires a passcode to be set up",
65+
reportedThreats.contains(
66+
ThreatDetectionCenter.Threat.DEVICE_WITHOUT_PASSCODE,
67+
),
68+
),
69+
ThreatStatus(
70+
"Hardware protection",
71+
"Refers to hardware capabilities of current device, specific to hardware-backed cryptography operations. If not available, no additional hardware security layer can be used when working with keys, certificates and keychain",
72+
reportedThreats.contains(
73+
ThreatDetectionCenter.Threat.HARDWARE_PROTECTION_UNAVAILABLE,
74+
),
75+
),
76+
ThreatStatus(
77+
"Signature missmatch",
78+
"Expects app to be signed with a given certificate. For PlayStore should match the one provided by the store via Play Console",
79+
detectionCenter.hasAppSignatureMissmatch("INVALID"),
80+
),
6181
)
6282

6383
LazyColumn(
6484
modifier = Modifier
65-
.padding(16.dp)
85+
.padding(16.dp),
6686
) {
6787
item {
6888
Spacer(modifier = Modifier.height(48.dp))
@@ -71,7 +91,7 @@ fun ThreatStatusList() {
7191
contentDescription = "stethoscope_24px",
7292
modifier = Modifier
7393
.fillMaxWidth()
74-
.size(80.dp)
94+
.size(80.dp),
7595
)
7696
Spacer(modifier = Modifier.height(24.dp))
7797
Text(
@@ -80,7 +100,7 @@ fun ThreatStatusList() {
80100
modifier = Modifier
81101
.fillMaxWidth()
82102
.padding(bottom = 8.dp),
83-
textAlign = TextAlign.Center
103+
textAlign = TextAlign.Center,
84104
)
85105
Text(
86106
text = "Here is a list of the threats that could put you at risk",
@@ -89,7 +109,7 @@ fun ThreatStatusList() {
89109
.fillMaxWidth()
90110
.padding(bottom = 16.dp),
91111
textAlign = TextAlign.Center,
92-
color = Color.Gray
112+
color = Color.Gray,
93113
)
94114
}
95115
items(threats) { item ->
@@ -98,7 +118,7 @@ fun ThreatStatusList() {
98118
.padding(8.dp)
99119
.fillMaxWidth(),
100120
shape = MaterialTheme.shapes.medium,
101-
elevation = CardDefaults.cardElevation(1.dp)
121+
elevation = CardDefaults.cardElevation(1.dp),
102122
) {
103123
ThreatStatusRow(threatStatus = item)
104124
}
@@ -112,4 +132,4 @@ private fun Preview() {
112132
MobileSecurityToolkitExampleTheme {
113133
ThreatStatusList()
114134
}
115-
}
135+
}

example/app/src/main/java/com/exxeta/mobilesecuritytoolkitexample/ThreatStatusRow.kt

+10-6
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,24 @@ fun ThreatStatusRow(threatStatus: ThreatStatus) {
4646
Box(
4747
modifier = Modifier
4848
.clip(RoundedCornerShape(CornerSize(size = 4.dp)))
49-
.background(if (threatStatus.isDetected) redColor else greenColor)
49+
.background(
50+
if (threatStatus.isDetected) redColor else greenColor,
51+
),
5052
) {
5153
Text(
5254
text = if (threatStatus.isDetected) "DETECTED" else "SAFE",
5355
color = MaterialTheme.colorScheme.background,
5456
style = MaterialTheme.typography.bodySmall,
5557
modifier = Modifier
5658
.padding(vertical = 2.dp)
57-
.padding(horizontal = 8.dp)
59+
.padding(horizontal = 8.dp),
5860
)
5961
}
6062
}
6163
Text(
6264
threatStatus.description,
6365
style = MaterialTheme.typography.titleMedium,
64-
color = Color.Gray
66+
color = Color.Gray,
6567
)
6668
}
6769
}
@@ -72,8 +74,10 @@ private fun Preview() {
7274
MobileSecurityToolkitExampleTheme {
7375
ThreatStatusRow(
7476
ThreatStatus(
75-
"Jailbreak", "Description", false,
76-
)
77+
"Jailbreak",
78+
"Description",
79+
false,
80+
),
7781
)
7882
}
79-
}
83+
}

example/app/src/main/java/com/exxeta/mobilesecuritytoolkitexample/ui/theme/Color.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ val Pink80 = Color(0xFFEFB8C8)
88

99
val Purple40 = Color(0xFF6650a4)
1010
val PurpleGrey40 = Color(0xFF625b71)
11-
val Pink40 = Color(0xFF7D5260)
11+
val Pink40 = Color(0xFF7D5260)
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.exxeta.mobilesecuritytoolkitexample.ui.theme
22

3-
import android.app.Activity
43
import android.os.Build
54
import androidx.compose.foundation.isSystemInDarkTheme
65
import androidx.compose.material3.MaterialTheme
@@ -14,13 +13,13 @@ import androidx.compose.ui.platform.LocalContext
1413
private val DarkColorScheme = darkColorScheme(
1514
primary = Purple80,
1615
secondary = PurpleGrey80,
17-
tertiary = Pink80
16+
tertiary = Pink80,
1817
)
1918

2019
private val LightColorScheme = lightColorScheme(
2120
primary = Purple40,
2221
secondary = PurpleGrey40,
23-
tertiary = Pink40
22+
tertiary = Pink40,
2423

2524
/* Other default colors to override
2625
background = Color(0xFFFFFBFE),
@@ -30,28 +29,34 @@ private val LightColorScheme = lightColorScheme(
3029
onTertiary = Color.White,
3130
onBackground = Color(0xFF1C1B1F),
3231
onSurface = Color(0xFF1C1B1F),
33-
*/
32+
*/
3433
)
3534

3635
@Composable
3736
fun MobileSecurityToolkitExampleTheme(
3837
darkTheme: Boolean = isSystemInDarkTheme(),
3938
// Dynamic color is available on Android 12+
4039
dynamicColor: Boolean = true,
41-
content: @Composable () -> Unit
40+
content: @Composable () -> Unit,
4241
) {
4342
val colorScheme = when {
44-
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
45-
val context = LocalContext.current
46-
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
47-
}
48-
darkTheme -> DarkColorScheme
49-
else -> LightColorScheme
43+
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
44+
val context = LocalContext.current
45+
if (darkTheme) {
46+
dynamicDarkColorScheme(
47+
context,
48+
)
49+
} else {
50+
dynamicLightColorScheme(context)
51+
}
52+
}
53+
darkTheme -> DarkColorScheme
54+
else -> LightColorScheme
5055
}
5156

5257
MaterialTheme(
53-
colorScheme = colorScheme,
54-
typography = Typography,
55-
content = content
58+
colorScheme = colorScheme,
59+
typography = Typography,
60+
content = content,
5661
)
57-
}
62+
}

example/app/src/main/java/com/exxeta/mobilesecuritytoolkitexample/ui/theme/Type.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ val Typography = Typography(
1313
fontWeight = FontWeight.Normal,
1414
fontSize = 16.sp,
1515
lineHeight = 24.sp,
16-
letterSpacing = 0.5.sp
17-
)
16+
letterSpacing = 0.5.sp,
17+
),
1818
/* Other default text styles to override
1919
titleLarge = TextStyle(
2020
fontFamily = FontFamily.Default,
@@ -30,5 +30,5 @@ val Typography = Typography(
3030
lineHeight = 16.sp,
3131
letterSpacing = 0.5.sp
3232
)
33-
*/
34-
)
33+
*/
34+
)

example/app/src/test/java/com/exxeta/mobilesecuritytoolkitexample/ExampleUnitTest.kt

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package com.exxeta.mobilesecuritytoolkitexample
22

3-
import org.junit.Test
4-
53
import org.junit.Assert.*
4+
import org.junit.Test
65

76
/**
87
* Example local unit test, which will execute on the development machine (host).
@@ -14,4 +13,4 @@ class ExampleUnitTest {
1413
fun addition_isCorrect() {
1514
assertEquals(4, 2 + 2)
1615
}
17-
}
16+
}

example/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
plugins {
33
alias(libs.plugins.android.application) apply false
44
alias(libs.plugins.jetbrains.kotlin.android) apply false
5-
}
5+
}

example/gradle/libs.versions.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
2525
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
2626
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
2727
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
28-
android-security-toolkit = { module = "com.github.EXXETA:Android-Security-Toolkit", version.ref = "androidSecurityToolkit" }
28+
android-security-toolkit = { module = "com.local.project:securitytoolkit", version.ref = "androidSecurityToolkit" }
2929

3030
[plugins]
3131
android-application = { id = "com.android.application", version.ref = "agp" }

0 commit comments

Comments
 (0)