feat: kick off a very basic passphrase cache

This commit is contained in:
Harsh Shandilya 2023-05-05 00:33:06 +05:30
parent 1e68e97b25
commit f9730cae58
No known key found for this signature in database

View file

@ -0,0 +1,67 @@
package app.passwordstore.data.crypto
import android.content.Context
import androidx.core.content.edit
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import app.passwordstore.crypto.GpgIdentifier
import app.passwordstore.util.coroutines.DispatcherProvider
import app.passwordstore.util.extensions.getString
import javax.inject.Inject
import kotlinx.coroutines.withContext
/** Implements a rudimentary [EncryptedSharedPreferences]-backed cache for GPG passphrases. */
@Suppress("Unused") // Soon
class GPGPassphraseCache
@Inject
constructor(
private val dispatcherProvider: DispatcherProvider,
) {
private suspend fun cachePassphrase(
context: Context,
identifier: GpgIdentifier,
passphrase: String,
) {
withContext(dispatcherProvider.io()) {
getPreferences(context).edit { putString(identifier.toString(), passphrase) }
}
}
private suspend fun retrieveCachedPassphrase(
context: Context,
identifier: GpgIdentifier,
): String? {
return withContext(dispatcherProvider.io()) {
getPreferences(context).getString(identifier.toString())
}
}
private suspend fun getPreferences(context: Context) =
withContext(dispatcherProvider.io()) {
EncryptedSharedPreferences.create(
context,
ANDROIDX_SECURITY_KEYSET_PREF_NAME,
getOrCreateWrappingMasterKey(context),
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
}
private suspend fun getOrCreateWrappingMasterKey(context: Context) =
withContext(dispatcherProvider.io()) {
MasterKey.Builder(context, "passphrase")
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.setRequestStrongBoxBacked(true)
.setUserAuthenticationRequired(
/* authenticationRequired = */ true,
/* userAuthenticationValidityDurationSeconds = */ 60,
)
.build()
}
private companion object {
private const val ANDROIDX_SECURITY_KEYSET_PREF_NAME = "androidx_passphrase_keyset_prefs"
}
}