Use EncryptedSharedPreferences for HMAC key storage
Replace plain-text SharedPreferences with AES256-GCM encrypted prefs via androidx.security:security-crypto. Adds PrefsHelper utility to centralize encrypted prefs access across MainActivity, SettingsActivity and UsbKeyReceiver. Reviewed in codereview.md (recommendation #2).
This commit is contained in:
parent
4a70f94a51
commit
b5d42d53ba
5 changed files with 42 additions and 10 deletions
|
|
@ -42,4 +42,5 @@ dependencies {
|
|||
implementation 'io.github.dkaukov:esp32-flash-lib:1.1.17'
|
||||
implementation 'com.eclipsesource.minimal-json:minimal-json:0.9.5'
|
||||
implementation 'org.slf4j:slf4j-nop:2.0.16'
|
||||
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
||||
}
|
||||
|
|
@ -164,8 +164,8 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun loadHmacKey() {
|
||||
val prefs = getSharedPreferences(SettingsActivity.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val hexKey = prefs.getString(SettingsActivity.PREF_KEY, null)
|
||||
val prefs = PrefsHelper.getPrefs(this)
|
||||
val hexKey = prefs.getString(PrefsHelper.PREF_KEY, null)
|
||||
hmacKey = hexKey?.let { hexStringToBytes(it) }
|
||||
Log.d(TAG, "HMAC key loaded: ${if (hmacKey != null) "${hmacKey!!.size} bytes" else "none"}")
|
||||
}
|
||||
|
|
|
|||
33
android/app/src/main/java/com/eddy/atomrelay/PrefsHelper.kt
Normal file
33
android/app/src/main/java/com/eddy/atomrelay/PrefsHelper.kt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package com.eddy.atomrelay
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import androidx.security.crypto.EncryptedSharedPreferences
|
||||
import androidx.security.crypto.MasterKey
|
||||
|
||||
object PrefsHelper {
|
||||
|
||||
private const val TAG = "PrefsHelper"
|
||||
const val PREFS_NAME = "relay_prefs"
|
||||
const val PREF_KEY = "hmac_key"
|
||||
|
||||
fun getPrefs(context: Context): SharedPreferences {
|
||||
return try {
|
||||
val masterKey = MasterKey.Builder(context)
|
||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
||||
.build()
|
||||
|
||||
EncryptedSharedPreferences.create(
|
||||
context,
|
||||
PREFS_NAME,
|
||||
masterKey,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to create EncryptedSharedPreferences", e)
|
||||
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,8 +27,6 @@ import java.security.SecureRandom
|
|||
class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
const val PREFS_NAME = "relay_prefs"
|
||||
const val PREF_KEY = "hmac_key"
|
||||
const val RESULT_SCAN = 100
|
||||
private const val TAG = "SettingsActivity"
|
||||
private const val ESP_VENDOR_ID = 0x303a
|
||||
|
|
@ -158,8 +156,8 @@ class SettingsActivity : AppCompatActivity() {
|
|||
handler.post {
|
||||
when (result) {
|
||||
is KeyResult.Success -> {
|
||||
val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
prefs.edit().putString(PREF_KEY, result.hexKey).apply()
|
||||
val prefs = PrefsHelper.getPrefs(this@SettingsActivity)
|
||||
prefs.edit().putString(PrefsHelper.PREF_KEY, result.hexKey).apply()
|
||||
Toast.makeText(this, "Beveiligingssleutel gelezen", Toast.LENGTH_LONG).show()
|
||||
cleanupAction()
|
||||
setResult(RESULT_SCAN)
|
||||
|
|
|
|||
|
|
@ -211,8 +211,8 @@ class UsbKeyReceiver : BroadcastReceiver() {
|
|||
val hexKey = keyLine.removePrefix("HMAC_KEY:").trim()
|
||||
if (hexKey.length == 64 && hexKey.all { it in "0123456789ABCDEFabcdef" }) {
|
||||
val upperKey = hexKey.uppercase()
|
||||
val prefs = context.getSharedPreferences(SettingsActivity.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
prefs.edit().putString(SettingsActivity.PREF_KEY, upperKey).apply()
|
||||
val prefs = PrefsHelper.getPrefs(context)
|
||||
prefs.edit().putString(PrefsHelper.PREF_KEY, upperKey).apply()
|
||||
Log.d(TAG, "HMAC key saved (${upperKey.length} chars)")
|
||||
handler.post {
|
||||
Toast.makeText(context, "Beveiligingssleutel gelezen", Toast.LENGTH_LONG).show()
|
||||
|
|
@ -248,8 +248,8 @@ class UsbKeyReceiver : BroadcastReceiver() {
|
|||
|
||||
if (okSb.contains("OK")) {
|
||||
Log.d(TAG, "Key provisioned successfully, saving to prefs")
|
||||
val prefs = context.getSharedPreferences(SettingsActivity.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
prefs.edit().putString(SettingsActivity.PREF_KEY, newKey).apply()
|
||||
val prefs = PrefsHelper.getPrefs(context)
|
||||
prefs.edit().putString(PrefsHelper.PREF_KEY, newKey).apply()
|
||||
handler.post {
|
||||
Toast.makeText(context, "Beveiligingssleutel gelezen", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue