From 1d00e5cdc6f3a1b6364a43d5f8d8ff906265dda0 Mon Sep 17 00:00:00 2001 From: "Tzouvaras, Stilianos" Date: Wed, 5 Jun 2024 18:58:42 +0300 Subject: [PATCH 1/5] Removed unused functionalities --- .../eu/europa/ec/assemblylogic/Application.kt | 23 -- .../ec/assemblylogic/ui/MainActivity.kt | 2 - .../config/ConfigSecurityLogic.kt | 74 ------- .../config/ConfigSecurityLogicImpl.kt | 22 -- .../security/AndroidPackageController.kt | 143 ------------- .../controller/security/AntiHookController.kt | 99 --------- .../controller/security/RootController.kt | 40 ---- .../controller/security/SecurityController.kt | 176 --------------- .../businesslogic/di/LogicBusinessModule.kt | 47 +--- .../controller/TestSecurityController.kt | 202 ------------------ gradle/libs.versions.toml | 3 - network-logic/build.gradle.kts | 3 - .../ec/networklogic/di/NetworkModule.kt | 11 +- ui-logic/build.gradle.kts | 3 - .../container/EudiComponentActivity.kt | 39 ---- 15 files changed, 2 insertions(+), 885 deletions(-) delete mode 100644 business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogic.kt delete mode 100644 business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogicImpl.kt delete mode 100644 business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AndroidPackageController.kt delete mode 100644 business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AntiHookController.kt delete mode 100644 business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/RootController.kt delete mode 100644 business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/SecurityController.kt delete mode 100644 business-logic/src/test/java/eu/europa/ec/businesslogic/controller/TestSecurityController.kt diff --git a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt index 8f6aad79..fa26a009 100644 --- a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt +++ b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/Application.kt @@ -17,10 +17,8 @@ package eu.europa.ec.assemblylogic import android.app.Application -import android.os.StrictMode import eu.europa.ec.analyticslogic.controller.AnalyticsController import eu.europa.ec.assemblylogic.di.setupKoin -import eu.europa.ec.businesslogic.config.ConfigSecurityLogic import eu.europa.ec.businesslogic.controller.log.LogController import eu.europa.ec.corelogic.config.WalletCoreConfig import eu.europa.ec.eudi.wallet.EudiWallet @@ -35,7 +33,6 @@ class Application : Application() { private val logController: LogController by inject() private val configWalletCore: WalletCoreConfig by inject() - private val configSecurityLogic: ConfigSecurityLogic by inject() private val analyticsController: AnalyticsController by inject() override fun onCreate() { @@ -45,7 +42,6 @@ class Application : Application() { initializeEudiWallet() initializeLogging() initializeTheme() - handleStrictMode() } private fun initializeReporting() { @@ -76,23 +72,4 @@ class Application : Application() { configWalletCore.config ) } - - private fun handleStrictMode() { - if (configSecurityLogic.enableStrictMode) { - StrictMode.setThreadPolicy( - StrictMode.ThreadPolicy.Builder() - .detectDiskReads() - .detectDiskWrites() - .detectNetwork() - .penaltyLog() - .build() - ) - StrictMode.setVmPolicy( - StrictMode.VmPolicy.Builder() - .detectAll() - .penaltyLog() - .build() - ) - } - } } \ No newline at end of file diff --git a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/ui/MainActivity.kt b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/ui/MainActivity.kt index 7bbdd44a..4d9ad837 100644 --- a/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/ui/MainActivity.kt +++ b/assembly-logic/src/main/java/eu/europa/ec/assemblylogic/ui/MainActivity.kt @@ -30,8 +30,6 @@ import eu.europa.ec.uilogic.container.EudiComponentActivity class MainActivity : EudiComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - windowFlags() setContent { Content(intent) { featureStartupGraph(it) diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogic.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogic.kt deleted file mode 100644 index ac09e73b..00000000 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogic.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.config - -interface ConfigSecurityLogic { - /** - * Check root access on startup for release builds. - */ - val blockRootAccess: Boolean get() = false - - /** - * Checks if any root cloaking apps are installed on startup for release builds. - */ - val blockRootCloakingAppsAccess: Boolean get() = false - - /** - * Checks for any hooks on startup for release builds. - */ - val blockHooks: Boolean get() = false - - /** - * Block running on emulator on startup for release builds. - */ - val blockEmulator: Boolean get() = false - - /** - * Block debug mode on startup for release builds. - */ - val blockDebugMode: Boolean get() = false - - /** - * Block screen capture for release builds. - */ - val blockScreenCapture: Boolean get() = false - - /** - * Validate package signature on startup for release builds. - */ - val packageSignature: String? get() = null - - /** - * Set trusted installers for release builds. - */ - val packageInstallers: List get() = emptyList() - - /** - * Activate Strict mode for Debug Builds - */ - val enableStrictMode: Boolean get() = false - - /** - * Use network logger for debug builds. - */ - val useNetworkLogger: Boolean get() = false - - /** - * Block overlay windows for release builds. - */ - val blockOverlayWindow: Boolean get() = false -} \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogicImpl.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogicImpl.kt deleted file mode 100644 index 4ee07e3d..00000000 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/config/ConfigSecurityLogicImpl.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.config - -class ConfigSecurityLogicImpl(private val configLogic: ConfigLogic) : ConfigSecurityLogic { - override val useNetworkLogger: Boolean - get() = configLogic.appBuildType == AppBuildType.DEBUG -} \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AndroidPackageController.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AndroidPackageController.kt deleted file mode 100644 index 4341328b..00000000 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AndroidPackageController.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.controller.security - -import android.annotation.SuppressLint -import android.content.pm.ApplicationInfo -import android.content.pm.PackageManager -import android.os.Build -import android.util.Base64 -import eu.europa.ec.businesslogic.controller.log.LogController -import eu.europa.ec.resourceslogic.provider.ResourceProvider -import java.nio.charset.StandardCharsets -import java.security.MessageDigest -import java.util.Arrays - -enum class AndroidInstaller { - TRUSTED, UNKNOWN -} - -interface AndroidPackageController { - fun getSignatures(): List - fun getInstaller(trusted: List): AndroidInstaller - fun isDebugModeEnabled(): Boolean - fun getSmsHashCodes(): List -} - -class AndroidPackageControllerImpl( - private val resourceProvider: ResourceProvider, - private val logController: LogController -) : AndroidPackageController { - - companion object { - private const val HASH_TYPE = "SHA-256" - private const val NUM_HASHED_BYTES = 9 - private const val NUM_BASE64_CHAR = 11 - } - - @Suppress("DEPRECATION") - @SuppressLint("PackageManagerGetSignatures") - override fun getSmsHashCodes(): List { - try { - - val packageName: String = resourceProvider.provideContext().packageName - val packageManager: PackageManager = resourceProvider.provideContext().packageManager - val packageInfo = packageManager.getPackageInfo( - packageName, - PackageManager.GET_SIGNATURES - ) - return packageInfo.signatures.mapNotNull { signature -> - hash(packageName, signature.toCharsString())?.let { - logController.d { "Hash $it" } - it - } - } - } catch (e: Exception) { - logController.e(javaClass.simpleName, e) - } - return emptyList() - } - - @Suppress("DEPRECATION") - @SuppressLint("PackageManagerGetSignatures") - override fun getSignatures(): List { - try { - val packageInfo = resourceProvider.provideContext().packageManager.getPackageInfo( - resourceProvider.provideContext().packageName, - PackageManager.GET_SIGNATURES - ) - return packageInfo.signatures.map { - val md: MessageDigest = MessageDigest.getInstance("SHA").apply { - update(it.toByteArray()) - } - Base64.encodeToString(md.digest(), Base64.DEFAULT).trim() - } - } catch (e: Exception) { - logController.e(javaClass.simpleName, e) - } - return emptyList() - } - - @Suppress("DEPRECATION") - override fun getInstaller(trusted: List): AndroidInstaller { - val packageManager = resourceProvider.provideContext().packageManager - val installer = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - packageManager.getInstallSourceInfo( - resourceProvider.provideContext().packageName - ).installingPackageName - } else { - packageManager.getInstallerPackageName( - resourceProvider.provideContext().packageName - ) - } - return installer?.let { - if (trusted.contains(it)) { - AndroidInstaller.TRUSTED - } else { - AndroidInstaller.UNKNOWN - } - } ?: AndroidInstaller.UNKNOWN - } - - override fun isDebugModeEnabled(): Boolean { - return 0 != resourceProvider.provideContext().applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE - } - - private fun hash(packageName: String, signature: String): String? { - val appInfo = "$packageName $signature" - try { - val messageDigest = MessageDigest.getInstance(HASH_TYPE) - messageDigest.update(appInfo.toByteArray(StandardCharsets.UTF_8)) - var hashSignature = messageDigest.digest() - hashSignature = Arrays.copyOfRange( - hashSignature, - 0, - NUM_HASHED_BYTES - ) - var base64Hash = Base64.encodeToString( - hashSignature, - Base64.NO_PADDING or Base64.NO_WRAP - ) - base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR) - logController.d { "pkg: $packageName -- hash: $base64Hash" } - return base64Hash - } catch (e: Exception) { - logController.e(javaClass.simpleName, e) - } - return null - } -} \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AntiHookController.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AntiHookController.kt deleted file mode 100644 index 5e7db881..00000000 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/AntiHookController.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.controller.security - -import android.os.Process -import eu.europa.ec.businesslogic.controller.log.LogController -import java.io.BufferedReader -import java.io.FileReader - -interface AntiHookController { - - fun isStacktraceHooked(): Boolean - - fun isMemoryHooked(): Boolean -} - -class AntiHookControllerImpl( - private val logController: LogController -) : AntiHookController { - - override fun isStacktraceHooked(): Boolean { - try { - throw Exception() - } catch (e: Exception) { - var zygoteInitCallCount = 0 - e.stackTrace.forEach { element -> - when { - "com.android.internal.os.ZygoteInit" == element.className -> { - zygoteInitCallCount++ - if (zygoteInitCallCount == 2) { - logController.d(this.javaClass.simpleName) { - "Substrate is active on the device." - } - return true - } - } - - "com.saurik.substrate.MS$2" == element.className && - "invoked" == element.methodName -> { - logController.d(this.javaClass.simpleName) { - "A method on the stack trace has been hooked using Substrate." - } - return true - } - - "de.robv.android.xposed.XposedBridge" == element.className && - "main" == element.methodName -> { - logController.d(this.javaClass.simpleName) { - "Xposed is active on the device." - } - return true - } - - "de.robv.android.xposed.XposedBridge" == element.className && - "handleHookedMethod" == element.methodName -> { - logController.d(this.javaClass.simpleName) { - "A method on the stack trace has been hooked using Xposed." - } - return true - } - } - } - return false - } - } - - override fun isMemoryHooked(): Boolean { - try { - val mapsFilename = "/proc/" + Process.myPid() + "/maps" - BufferedReader(FileReader(mapsFilename)).use { reader -> - val libraries = reader.readLines().filter { line -> - val n = line.lastIndexOf(" ") - val library = line.substring(n + 1) - (line.endsWith(".so") || line.endsWith(".jar")) && - library.contains("com.saurik.substrate") || - library.contains("XposedBridge.jar") - } - return libraries.isNotEmpty() - } - } catch (e: Exception) { - logController.e(javaClass.simpleName, e) - return false - } - } -} \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/RootController.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/RootController.kt deleted file mode 100644 index 8dc4b918..00000000 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/RootController.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.controller.security - -import com.scottyab.rootbeer.RootBeer -import eu.europa.ec.resourceslogic.provider.ResourceProvider - -interface RootController { - fun isRooted(): Boolean - fun areRootCloakingAppsInstalled(): Boolean -} - -class RootControllerImpl( - resourceProvider: ResourceProvider -) : RootController { - - private val rootBeer = RootBeer(resourceProvider.provideContext()) - - override fun isRooted() = rootBeer.isRooted - - override fun areRootCloakingAppsInstalled() = rootBeer.detectRootCloakingApps( - arrayOf( - "com.android.SSLTrustKiller" - ) - ) -} \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/SecurityController.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/SecurityController.kt deleted file mode 100644 index a51246bf..00000000 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/controller/security/SecurityController.kt +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.controller.security - -import android.os.Build -import eu.europa.ec.businesslogic.config.AppBuildType -import eu.europa.ec.businesslogic.config.ConfigLogic -import eu.europa.ec.businesslogic.config.ConfigSecurityLogic -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOn - -interface SecurityController { - fun isRunningOnEmulator(): Boolean - fun isDeviceRooted(): Boolean - fun isSignatureValid(): Boolean - fun isPackageInstallerValid(): Boolean - fun isDebugModeEnabled(): Boolean - fun areRootCloakingAppsInstalled(): Boolean - fun isHookDetected(): Boolean - fun blockScreenCapture(): Boolean - fun blockOverlayWindow(): Boolean - fun isApplicationSecure(): Flow -} - -class SecurityControllerImpl( - private val configLogic: ConfigLogic, - private val configSecurityLogic: ConfigSecurityLogic, - private val rootController: RootController, - private val antiHookController: AntiHookController, - private val androidPackageController: AndroidPackageController -) : SecurityController { - - override fun isRunningOnEmulator() = - configLogic.appBuildType == AppBuildType.RELEASE - && configSecurityLogic.blockEmulator - && ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) - || Build.FINGERPRINT.startsWith("generic") - || Build.FINGERPRINT.startsWith("unknown") - || Build.HARDWARE.contains("goldfish") - || Build.HARDWARE.contains("ranchu") - || Build.MODEL.contains("google_sdk") - || Build.MODEL.contains("Emulator") - || Build.MODEL.contains("Android SDK built for x86") - || Build.MANUFACTURER.contains("Genymotion") - || Build.PRODUCT.contains("sdk_google") - || Build.PRODUCT.contains("google_sdk") - || Build.PRODUCT.contains("sdk") - || Build.PRODUCT.contains("sdk_x86") - || Build.PRODUCT.contains("sdk_gphone64_arm64") - || Build.PRODUCT.contains("vbox86p") - || Build.PRODUCT.contains("emulator") - || Build.PRODUCT.contains("simulator") - || Build.PRODUCT.contains("robolectric")) - - override fun isDeviceRooted(): Boolean = - configLogic.appBuildType == AppBuildType.RELEASE - && configSecurityLogic.blockRootAccess - && rootController.isRooted() - - override fun isSignatureValid(): Boolean { - if (configLogic.appBuildType != AppBuildType.RELEASE || configSecurityLogic.packageSignature == null) { - return true - } - for (signature in androidPackageController.getSignatures()) { - if (signature == configSecurityLogic.packageSignature) { - return true - } - } - return false - } - - override fun isPackageInstallerValid(): Boolean { - if (configLogic.appBuildType != AppBuildType.RELEASE || configSecurityLogic.packageInstallers.isEmpty()) { - return true - } - return when (androidPackageController.getInstaller(configSecurityLogic.packageInstallers)) { - AndroidInstaller.TRUSTED -> true - AndroidInstaller.UNKNOWN -> false - } - } - - override fun isDebugModeEnabled(): Boolean { - return configLogic.appBuildType == AppBuildType.RELEASE - && androidPackageController.isDebugModeEnabled() - && configSecurityLogic.blockDebugMode - } - - override fun areRootCloakingAppsInstalled(): Boolean = - configLogic.appBuildType == AppBuildType.RELEASE - && configSecurityLogic.blockRootCloakingAppsAccess - && rootController.areRootCloakingAppsInstalled() - - override fun isHookDetected(): Boolean = - configLogic.appBuildType == AppBuildType.RELEASE - && configSecurityLogic.blockHooks - && (antiHookController.isMemoryHooked() || antiHookController.isStacktraceHooked()) - - override fun isApplicationSecure(): Flow = flow { - val isRunningOnEmulator = isRunningOnEmulator() - val isDeviceRooted = isDeviceRooted() - val isSignatureValid = isSignatureValid() - val isPackageInstallerValid = isPackageInstallerValid() - val isDebugModeEnabled = isDebugModeEnabled() - val isHookDetected = isHookDetected() - val areRootCloakingAppsInstalled = areRootCloakingAppsInstalled() - emit( - SecurityValidation( - isRunningOnEmulator = isRunningOnEmulator, - isDeviceRooted = isDeviceRooted, - isSignatureValid = isSignatureValid, - isPackageInstallerValid = isPackageInstallerValid, - isDebugModeEnabled = isDebugModeEnabled, - areRootCloakingAppsInstalled = areRootCloakingAppsInstalled, - isHookDetected = isHookDetected, - serviceErrorCode = when { - isRunningOnEmulator -> SecurityErrorCode.EMULATOR - isDeviceRooted -> SecurityErrorCode.ROOT - !isSignatureValid -> SecurityErrorCode.SIGNATURE - !isPackageInstallerValid -> SecurityErrorCode.PACKAGE_INSTALLER - isDebugModeEnabled -> SecurityErrorCode.DEBUGGABLE - areRootCloakingAppsInstalled -> SecurityErrorCode.ROOT_CLOAKING_APPS - isHookDetected -> SecurityErrorCode.HOOK - else -> SecurityErrorCode.UNKNOWN - } - ) - ) - }.flowOn(Dispatchers.IO) - - override fun blockScreenCapture(): Boolean { - return configSecurityLogic.blockScreenCapture && configLogic.appBuildType == AppBuildType.RELEASE - } - - override fun blockOverlayWindow(): Boolean { - return configSecurityLogic.blockOverlayWindow - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S - && configLogic.appBuildType == AppBuildType.RELEASE - } -} - -data class SecurityValidation( - val isRunningOnEmulator: Boolean, - val isDeviceRooted: Boolean, - val isSignatureValid: Boolean, - val isPackageInstallerValid: Boolean, - val isDebugModeEnabled: Boolean, - val areRootCloakingAppsInstalled: Boolean, - val isHookDetected: Boolean, - val serviceErrorCode: SecurityErrorCode -) - -enum class SecurityErrorCode(val code: String) { - EMULATOR("1001"), - ROOT("1002"), - SIGNATURE("1003"), - PACKAGE_INSTALLER("1004"), - DEBUGGABLE("1005"), - ROOT_CLOAKING_APPS("1006"), - HOOK("1007"), - UNKNOWN("1000") -} \ No newline at end of file diff --git a/business-logic/src/main/java/eu/europa/ec/businesslogic/di/LogicBusinessModule.kt b/business-logic/src/main/java/eu/europa/ec/businesslogic/di/LogicBusinessModule.kt index 85a8d02e..6bc005c3 100644 --- a/business-logic/src/main/java/eu/europa/ec/businesslogic/di/LogicBusinessModule.kt +++ b/business-logic/src/main/java/eu/europa/ec/businesslogic/di/LogicBusinessModule.kt @@ -18,22 +18,12 @@ package eu.europa.ec.businesslogic.di import eu.europa.ec.businesslogic.config.ConfigLogic import eu.europa.ec.businesslogic.config.ConfigLogicImpl -import eu.europa.ec.businesslogic.config.ConfigSecurityLogic -import eu.europa.ec.businesslogic.config.ConfigSecurityLogicImpl import eu.europa.ec.businesslogic.controller.crypto.CryptoController import eu.europa.ec.businesslogic.controller.crypto.CryptoControllerImpl import eu.europa.ec.businesslogic.controller.crypto.KeystoreController import eu.europa.ec.businesslogic.controller.crypto.KeystoreControllerImpl import eu.europa.ec.businesslogic.controller.log.LogController import eu.europa.ec.businesslogic.controller.log.LogControllerImpl -import eu.europa.ec.businesslogic.controller.security.AndroidPackageController -import eu.europa.ec.businesslogic.controller.security.AndroidPackageControllerImpl -import eu.europa.ec.businesslogic.controller.security.AntiHookController -import eu.europa.ec.businesslogic.controller.security.AntiHookControllerImpl -import eu.europa.ec.businesslogic.controller.security.RootController -import eu.europa.ec.businesslogic.controller.security.RootControllerImpl -import eu.europa.ec.businesslogic.controller.security.SecurityController -import eu.europa.ec.businesslogic.controller.security.SecurityControllerImpl import eu.europa.ec.businesslogic.controller.storage.PrefKeys import eu.europa.ec.businesslogic.controller.storage.PrefKeysImpl import eu.europa.ec.businesslogic.controller.storage.PrefsController @@ -53,10 +43,6 @@ class LogicBusinessModule @Single fun provideConfigLogic(): ConfigLogic = ConfigLogicImpl() -@Single -fun provideConfigSecurityLogic(configLogic: ConfigLogic): ConfigSecurityLogic = - ConfigSecurityLogicImpl(configLogic) - @Single fun provideLogController(configLogic: ConfigLogic): LogController = LogControllerImpl(configLogic) @@ -82,35 +68,4 @@ fun provideCryptoController(keystoreController: KeystoreController): CryptoContr @Factory fun provideFormValidator(logController: LogController): FormValidator = - FormValidatorImpl(logController) - -@Factory -fun provideAndroidPackageController( - resourceProvider: ResourceProvider, - logController: LogController -): AndroidPackageController = - AndroidPackageControllerImpl(resourceProvider, logController) - -@Factory -fun provideAntiHookController(logController: LogController): AntiHookController = - AntiHookControllerImpl(logController) - -@Factory -fun provideRootController(resourceProvider: ResourceProvider): RootController = - RootControllerImpl(resourceProvider) - -@Factory -fun provideSecurityController( - configLogic: ConfigLogic, - configSecurityLogic: ConfigSecurityLogic, - rootController: RootController, - antiHookController: AntiHookController, - androidPackageController: AndroidPackageController -): SecurityController = - SecurityControllerImpl( - configLogic, - configSecurityLogic, - rootController, - antiHookController, - androidPackageController - ) \ No newline at end of file + FormValidatorImpl(logController) \ No newline at end of file diff --git a/business-logic/src/test/java/eu/europa/ec/businesslogic/controller/TestSecurityController.kt b/business-logic/src/test/java/eu/europa/ec/businesslogic/controller/TestSecurityController.kt deleted file mode 100644 index e38b13ae..00000000 --- a/business-logic/src/test/java/eu/europa/ec/businesslogic/controller/TestSecurityController.kt +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2023 European Commission - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work - * except in compliance with the Licence. - * - * You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF - * ANY KIND, either express or implied. See the Licence for the specific language - * governing permissions and limitations under the Licence. - */ - -package eu.europa.ec.businesslogic.controller - -import eu.europa.ec.businesslogic.config.AppBuildType -import eu.europa.ec.businesslogic.config.ConfigLogic -import eu.europa.ec.businesslogic.config.ConfigSecurityLogic -import eu.europa.ec.businesslogic.controller.security.AndroidInstaller -import eu.europa.ec.businesslogic.controller.security.AndroidPackageController -import eu.europa.ec.businesslogic.controller.security.AntiHookController -import eu.europa.ec.businesslogic.controller.security.RootController -import eu.europa.ec.businesslogic.controller.security.SecurityControllerImpl -import eu.europa.ec.testlogic.base.TestApplication -import junit.framework.TestCase.assertFalse -import junit.framework.TestCase.assertTrue -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.MockitoAnnotations -import org.mockito.Spy -import org.mockito.kotlin.whenever -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config - -@RunWith(RobolectricTestRunner::class) -@Config(application = TestApplication::class) -class TestSecurityController { - - @Spy - private lateinit var rootController: RootController - - @Spy - private lateinit var configLogic: ConfigLogic - - @Spy - private lateinit var configSecurityLogic: ConfigSecurityLogic - - @Spy - private lateinit var androidPackageController: AndroidPackageController - - @Spy - private lateinit var antiHookController: AntiHookController - - private lateinit var securityController: SecurityControllerImpl - - private val signature = "SIGNATURE" - private val installers = listOf("com.test") - - @Before - fun before() { - MockitoAnnotations.openMocks(this) - securityController = SecurityControllerImpl( - configLogic, - configSecurityLogic, - rootController, - antiHookController, - androidPackageController - ) - MockitoAnnotations.openMocks(this) - - whenever(configLogic.appBuildType).thenReturn(AppBuildType.RELEASE) - whenever(androidPackageController.getSignatures()).thenReturn(listOf(signature)) - } - - @Test - fun testIsRunningOnEmulatorWithBlockEmulatorConfigTrue() { - whenever(configSecurityLogic.blockEmulator).thenReturn(true) - assertTrue(securityController.isRunningOnEmulator()) - } - - @Test - fun testIsRunningOnEmulatorWithBlockEmulatorConfigFalse() { - whenever(configSecurityLogic.blockEmulator).thenReturn(false) - assertFalse(securityController.isRunningOnEmulator()) - } - - @Test - fun testIsDeviceRootedWithBlockRootAccessConfigTrue() { - whenever(configSecurityLogic.blockRootAccess).thenReturn(true) - whenever(rootController.isRooted()).thenReturn(true) - assertTrue(securityController.isDeviceRooted()) - } - - @Test - fun testIsDeviceRootedWithBlockRootAccessConfigFalse() { - whenever(configSecurityLogic.blockRootAccess).thenReturn(false) - whenever(rootController.isRooted()).thenReturn(true) - assertFalse(securityController.isDeviceRooted()) - } - - @Test - fun testIsSignatureValidWithSignaturePackageNotNullAndValid() { - whenever(configSecurityLogic.packageSignature).thenReturn(signature) - assertTrue(securityController.isSignatureValid()) - } - - @Test - fun testIsSignatureValidWithSignaturePackageNotNullAndNotValid() { - whenever(configSecurityLogic.packageSignature).thenReturn("") - assertFalse(securityController.isSignatureValid()) - } - - @Test - fun testIsSignatureValidWithSignaturePackageConfigIsNull() { - whenever(configSecurityLogic.packageSignature).thenReturn(null) - assertTrue(securityController.isSignatureValid()) - } - - @Test - fun testIsPackageInstallerValidWithConfigPackageInstallersNotEmptyAndValidInstaller() { - whenever(configSecurityLogic.packageInstallers).thenReturn(installers) - whenever(androidPackageController.getInstaller(installers)) - .thenReturn(AndroidInstaller.TRUSTED) - assertTrue(securityController.isPackageInstallerValid()) - } - - @Test - fun testIsPackageInstallerValidWithConfigPackageInstallersNotEmptyAndInValidInstaller() { - whenever(configSecurityLogic.packageInstallers).thenReturn(installers) - whenever(androidPackageController.getInstaller(installers)) - .thenReturn(AndroidInstaller.UNKNOWN) - assertFalse(securityController.isPackageInstallerValid()) - } - - @Test - fun testIsPackageInstallerValidWithConfigPackageInstallersEmpty() { - whenever(configSecurityLogic.packageInstallers).thenReturn(emptyList()) - assertTrue(securityController.isPackageInstallerValid()) - } - - @Test - fun testIsDebugModeEnabledWithConfigBlockDebugModeEnabledAndFlagDebuggable() { - whenever(configSecurityLogic.blockDebugMode).thenReturn(true) - whenever(androidPackageController.isDebugModeEnabled()).thenReturn(true) - assertTrue(securityController.isDebugModeEnabled()) - } - - @Test - fun testIsDebugModeEnabledWithConfigBlockDebugModeEnabledAndFlagNotDebuggable() { - whenever(configSecurityLogic.blockDebugMode).thenReturn(true) - whenever(androidPackageController.isDebugModeEnabled()).thenReturn(false) - assertFalse(securityController.isDebugModeEnabled()) - } - - @Test - fun testBlockScreenCaptureWithConfigBlockScreenCaptureEnabled() { - whenever(configSecurityLogic.blockScreenCapture).thenReturn(true) - assertTrue(securityController.blockScreenCapture()) - } - - @Test - fun testBlockScreenCaptureWithConfigBlockScreenCaptureDisabled() { - whenever(configSecurityLogic.blockScreenCapture).thenReturn(false) - assertFalse(securityController.blockScreenCapture()) - } - - @Test - fun testIsHookDetectedWithConfigBlockHooksEnabledAndReleaseBuildAndIsStackTracedHookDetectedAndIsMemoryHookedDetected() { - whenever(configSecurityLogic.blockHooks).thenReturn(true) - whenever(antiHookController.isMemoryHooked()).thenReturn(true) - whenever(antiHookController.isStacktraceHooked()).thenReturn(true) - assertTrue(securityController.isHookDetected()) - } - - @Test - fun testIsHookDetectedWithConfigBlockHooksEnabledAndReleaseBuildAndIsStackTracedHookDetectedAndIsMemoryHookedNotDetected() { - whenever(configSecurityLogic.blockHooks).thenReturn(true) - whenever(antiHookController.isMemoryHooked()).thenReturn(false) - whenever(antiHookController.isStacktraceHooked()).thenReturn(true) - assertTrue(securityController.isHookDetected()) - } - - @Test - fun testIsHookDetectedWithConfigBlockHooksEnabledAndReleaseBuildAndIsStackTracedHookNotDetectedAndIsMemoryHookedNotDetected() { - whenever(configSecurityLogic.blockHooks).thenReturn(true) - whenever(antiHookController.isMemoryHooked()).thenReturn(false) - whenever(antiHookController.isStacktraceHooked()).thenReturn(false) - assertFalse(securityController.isHookDetected()) - } - - @Test - fun testIsHookDetectedWithConfigBlockHooksDisabledAndReleaseBuildAndIsStackTracedHookDetectedAndIsMemoryHookedDetected() { - whenever(configSecurityLogic.blockHooks).thenReturn(false) - whenever(antiHookController.isMemoryHooked()).thenReturn(true) - whenever(antiHookController.isStacktraceHooked()).thenReturn(true) - assertFalse(securityController.isHookDetected()) - } -} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ab4f327c..e56e1497 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -55,7 +55,6 @@ material = "1.12.0" mockito = "5.12.0" mockitoKotlin = "5.3.1" mockitoInline = "5.2.0" -chucker = "4.0.0" ktor = "2.3.7" slf4j = "2.0.7" rootbeer = "0.1.0" @@ -146,8 +145,6 @@ koin-ksp = { group = "io.insert-koin", name = "koin-ksp-compiler", version.ref = mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" } mockito-kotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version.ref = "mockitoKotlin" } mockito-inline = { group = "org.mockito", name = "mockito-inline", version.ref = "mockitoInline" } -chucker-android = { group = "com.github.chuckerteam.chucker", name = "library", version.ref = "chucker" } -chucker-android-no-op = { group = "com.github.chuckerteam.chucker", name = "library-no-op", version.ref = "chucker" } ktor-android = { group = "io.ktor", name = "ktor-client-android", version.ref = "ktor" } ktor-logging = { group = "io.ktor", name = "ktor-client-logging", version.ref = "ktor" } slf4j = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" } diff --git a/network-logic/build.gradle.kts b/network-logic/build.gradle.kts index 7ed2ddc2..fa7fa8a4 100644 --- a/network-logic/build.gradle.kts +++ b/network-logic/build.gradle.kts @@ -38,9 +38,6 @@ dependencies { implementation(libs.okhttp.logging) implementation(libs.okhttp.mockwebserver) - debugImplementation(libs.chucker.android) - releaseImplementation(libs.chucker.android.no.op) - testImplementation(project(LibraryModule.TestLogic.path)) } diff --git a/network-logic/src/main/java/eu/europa/ec/networklogic/di/NetworkModule.kt b/network-logic/src/main/java/eu/europa/ec/networklogic/di/NetworkModule.kt index 0cbad1de..a32f4f4f 100644 --- a/network-logic/src/main/java/eu/europa/ec/networklogic/di/NetworkModule.kt +++ b/network-logic/src/main/java/eu/europa/ec/networklogic/di/NetworkModule.kt @@ -16,11 +16,8 @@ package eu.europa.ec.networklogic.di -import android.content.Context -import com.chuckerteam.chucker.api.ChuckerInterceptor import eu.europa.ec.businesslogic.config.AppBuildType import eu.europa.ec.businesslogic.config.ConfigLogic -import eu.europa.ec.businesslogic.config.ConfigSecurityLogic import eu.europa.ec.networklogic.api.Api import eu.europa.ec.networklogic.api.ApiClient import eu.europa.ec.networklogic.api.ApiClientImpl @@ -49,10 +46,8 @@ fun providesHttpLoggingInterceptor(configLogic: ConfigLogic) = HttpLoggingInterc @Factory fun provideOkHttpClient( - context: Context, httpLoggingInterceptor: HttpLoggingInterceptor, - configLogic: ConfigLogic, - configSecurityLogic: ConfigSecurityLogic + configLogic: ConfigLogic ): OkHttpClient { val client = OkHttpClient().newBuilder() @@ -60,10 +55,6 @@ fun provideOkHttpClient( .connectTimeout(configLogic.environmentConfig.connectTimeoutSeconds, TimeUnit.SECONDS) .addInterceptor(httpLoggingInterceptor) - if (configSecurityLogic.useNetworkLogger) { - client.addInterceptor(ChuckerInterceptor.Builder(context).build()) - } - return client.build() } diff --git a/ui-logic/build.gradle.kts b/ui-logic/build.gradle.kts index fc8ca3a9..9932ef6c 100644 --- a/ui-logic/build.gradle.kts +++ b/ui-logic/build.gradle.kts @@ -40,9 +40,6 @@ dependencies { implementation(libs.zxing) implementation(libs.gson) - debugImplementation(libs.chucker.android) - releaseImplementation(libs.chucker.android.no.op) - testImplementation(project(LibraryModule.TestLogic.path)) } diff --git a/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt b/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt index a9b838c1..3400b00c 100644 --- a/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt +++ b/ui-logic/src/main/java/eu/europa/ec/uilogic/container/EudiComponentActivity.kt @@ -16,25 +16,17 @@ package eu.europa.ec.uilogic.container -import android.Manifest -import android.annotation.SuppressLint import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri -import android.os.Build -import android.view.WindowManager import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.core.content.ContextCompat import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder -import com.chuckerteam.chucker.api.Chucker -import eu.europa.ec.businesslogic.controller.security.SecurityController import eu.europa.ec.resourceslogic.theme.ThemeManager import eu.europa.ec.uilogic.navigation.RouterHost import eu.europa.ec.uilogic.navigation.helper.DeepLinkType @@ -49,7 +41,6 @@ import org.koin.core.annotation.KoinExperimentalAPI open class EudiComponentActivity : FragmentActivity() { private val routerHost: RouterHost by inject() - private val securityController: SecurityController by inject() private var flowStarted: Boolean = false @@ -76,7 +67,6 @@ open class EudiComponentActivity : FragmentActivity() { } flowStarted = true handleDeepLink(intent, coldBoot = true) - ChuckerPermissions() } } } @@ -127,33 +117,4 @@ open class EudiComponentActivity : FragmentActivity() { setIntent(Intent()) } } - - protected fun windowFlags() { - if (securityController.blockScreenCapture()) { - window.setFlags( - WindowManager.LayoutParams.FLAG_SECURE, - WindowManager.LayoutParams.FLAG_SECURE - ) - } - @SuppressLint("MissingPermission", "NewApi") - if (securityController.blockOverlayWindow()) { - window.setHideOverlayWindows(true) - } - } - - @Composable - private fun ChuckerPermissions() { - if (Chucker.isOp - && ContextCompat.checkSelfPermission( - this, - Manifest.permission.POST_NOTIFICATIONS - ) != PackageManager.PERMISSION_GRANTED - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU - ) { - requestPermissions( - arrayOf(Manifest.permission.POST_NOTIFICATIONS), - 1000 - ) - } - } } \ No newline at end of file From e378aa3422857056fd85435a701aefb36112d127 Mon Sep 17 00:00:00 2001 From: "Tzouvaras, Stilianos" Date: Wed, 5 Jun 2024 19:21:44 +0300 Subject: [PATCH 2/5] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 357b11de..87935dc3 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ the [EUDI Wallet Reference Implementation project description](https://github.co * [Overview](#overview) * [Disclaimer](#disclaimer) +* [Important things to know](#important-things-to-know) * [How to contribute](#how-to-contribute) * [Demo videos](#demo-videos) * [How to use the application](#how-to-use-the-application) @@ -71,10 +72,21 @@ The released software is an initial development release version: - The initial development release may contain errors or design flaws and other problems that could cause system or other failures and data loss. - The initial development release has reduced security, privacy, availability, and reliability standards relative to future releases. This could make the software slower, less reliable, or more vulnerable to attacks than mature software. - The initial development release is not yet comprehensively documented. -- Users of the software must perform sufficient engineering and additional testing in order to properly evaluate their application and determine whether any of the open-sourced components is suitable for use in that application. +- Users of the software must perform sufficient engineering and additional testing to properly evaluate their application and determine whether any of the open-sourced components are suitable for use in that application. - We strongly recommend not putting this version of the software into production use. - Only the latest version of the software will be supported +## Important things to know + +The main purpose of the reference wallet implementation is to showcase the ecosystem and act as a technical example of how to integrate and use all of the available components. + +If you're planning to use it as a production application, we recommend reviewing the following steps: +- Configure the application properly by following the guide here: https://github.com/niscy-eudiw/eudi-app-android-wallet-ui/blob/main/wiki/configuration.md +- Ensure the PIN storage configuration matches your security requirements or provide your own by following this guide: https://github.com/niscy-eudiw/eudi-app-android-wallet-ui/blob/main/wiki/configuration.md#pin-storage-configuration +- Ensure the application meets the OWASP MASVS industry standard. Please refer to the following links for further information on the controls you must implement to ensure maximum compliance: + - https://mas.owasp.org/MASVS/ + - https://developer.android.com/google/play/integrity + ## How to contribute We welcome contributions to this project. To ensure that the process is smooth for everyone From 7559470d58ab6238f94a6f7983f62216bf955204 Mon Sep 17 00:00:00 2001 From: "Tzouvaras, Stilianos" Date: Wed, 5 Jun 2024 19:26:40 +0300 Subject: [PATCH 3/5] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 87935dc3..f6c57c3e 100644 --- a/README.md +++ b/README.md @@ -81,11 +81,11 @@ The released software is an initial development release version: The main purpose of the reference wallet implementation is to showcase the ecosystem and act as a technical example of how to integrate and use all of the available components. If you're planning to use it as a production application, we recommend reviewing the following steps: -- Configure the application properly by following the guide here: https://github.com/niscy-eudiw/eudi-app-android-wallet-ui/blob/main/wiki/configuration.md -- Ensure the PIN storage configuration matches your security requirements or provide your own by following this guide: https://github.com/niscy-eudiw/eudi-app-android-wallet-ui/blob/main/wiki/configuration.md#pin-storage-configuration +- Configure the application properly by following the guide [here](wiki/configuration.md) +- Ensure the PIN storage configuration matches your security requirements or provide your own by following this guide [Pin Storage Configuration](wiki/configuration.md#pin-storage-configuration) - Ensure the application meets the OWASP MASVS industry standard. Please refer to the following links for further information on the controls you must implement to ensure maximum compliance: - - https://mas.owasp.org/MASVS/ - - https://developer.android.com/google/play/integrity + - [OWASP MASVS](https://mas.owasp.org/MASVS/) + - [Play Integrity API](https://developer.android.com/google/play/integrity) ## How to contribute From 288e84527d2e3203fea80ae01eb6c91e646edc9e Mon Sep 17 00:00:00 2001 From: "Tzouvaras, Stilianos" Date: Wed, 5 Jun 2024 19:28:33 +0300 Subject: [PATCH 4/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6c57c3e..7db7807a 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ The main purpose of the reference wallet implementation is to showcase the ecosy If you're planning to use it as a production application, we recommend reviewing the following steps: - Configure the application properly by following the guide [here](wiki/configuration.md) -- Ensure the PIN storage configuration matches your security requirements or provide your own by following this guide [Pin Storage Configuration](wiki/configuration.md#pin-storage-configuration) +- Ensure the Pin storage configuration matches your security requirements or provide your own by following this guide [Pin Storage Configuration](wiki/configuration.md#pin-storage-configuration) - Ensure the application meets the OWASP MASVS industry standard. Please refer to the following links for further information on the controls you must implement to ensure maximum compliance: - [OWASP MASVS](https://mas.owasp.org/MASVS/) - [Play Integrity API](https://developer.android.com/google/play/integrity) From 1f60e98866a683dd102308c5426f4455cb003152 Mon Sep 17 00:00:00 2001 From: "Tzouvaras, Stilianos" Date: Wed, 5 Jun 2024 19:30:03 +0300 Subject: [PATCH 5/5] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7db7807a..cba2950c 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,9 @@ The released software is an initial development release version: ## Important things to know -The main purpose of the reference wallet implementation is to showcase the ecosystem and act as a technical example of how to integrate and use all of the available components. +The main purpose of the reference implementation is to showcase the ecosystem and act as a technical example of how to integrate and use all of the available components. -If you're planning to use it as a production application, we recommend reviewing the following steps: +If you're planning to use this application in production, we recommend reviewing the following steps: - Configure the application properly by following the guide [here](wiki/configuration.md) - Ensure the Pin storage configuration matches your security requirements or provide your own by following this guide [Pin Storage Configuration](wiki/configuration.md#pin-storage-configuration) - Ensure the application meets the OWASP MASVS industry standard. Please refer to the following links for further information on the controls you must implement to ensure maximum compliance: