Skip to content

Instantly share code, notes, and snippets.

@rynkowsg
Created March 6, 2024 16:03
Show Gist options
  • Save rynkowsg/86ebd680a67669dfcece4cc9ec9974df to your computer and use it in GitHub Desktop.
Save rynkowsg/86ebd680a67669dfcece4cc9ec9974df to your computer and use it in GitHub Desktop.
Get EncryptedSharedPreferences
//
// Get EncryptedSharedPreferences and handle restore of accidentallly
// backuped file that we can no longer decrypt. If the master key provided
// is not able to decrypt the shared preferences, the file will be recreated.
//
// Tested with "androidx.security:security-crypto:1.1.0-alpha06"
//
package pl.rynkowski.platform_utils
import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import java.security.KeyStore
import timber.log.Timber
private const val appMasterKeyAlias = "custom_master_key"
fun Context.getMasterKey(): MasterKey {
val keystore = KeyStore.getInstance("AndroidKeyStore")
keystore.load(null)
val masterKeyAlias =
if (keystore.isKeyEntry(appMasterKeyAlias)) appMasterKeyAlias
else MasterKey.DEFAULT_MASTER_KEY_ALIAS
return MasterKey.Builder(this, masterKeyAlias)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
}
fun Context.getEncryptedSharedPreferences(filename: String): SharedPreferences {
val masterKey = getMasterKey()
// Return the shared preferences if we can
val sharedPreferences = getEncryptedSharedPreferencesOrNull(filename, masterKey)
return sharedPreferences ?: run {
// otherwise delete and try again
Timber.w("Cannot retrieve preferences encrypted with current master key. Deleting and recreating.")
deleteSharedPreferences(filename)
return getEncryptedSharedPreferencesOrThrow(filename, masterKey)
}
}
fun Context.getEncryptedSharedPreferencesOrNull(filename: String, key: MasterKey): SharedPreferences? =
try {
getEncryptedSharedPreferencesOrThrow(filename = filename, key = key)
} catch (e: Exception) {
null
}
fun Context.getEncryptedSharedPreferencesOrThrow(filename: String, key: MasterKey): SharedPreferences =
EncryptedSharedPreferences.create(
this,
filename,
key,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
fun Context.getSharedPrefs(filename: String, encrypted: Boolean = false): SharedPreferences =
if (encrypted) {
getEncryptedSharedPreferences(filename)
} else {
getSharedPreferences(filename, Context.MODE_PRIVATE)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment