Files
gudari/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsSerializer.kt
T

54 lines
2.1 KiB
Kotlin

package com.bitcointxoko.gudariwallet.security
import android.util.Log
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer
import com.google.crypto.tink.StreamingAead
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.InputStream
import java.io.OutputStream
class CredentialsSerializer(
private val streamingAead: StreamingAead
) : Serializer<Credentials> {
private val TAG = "CredentialsSerializer"
override val defaultValue: Credentials = Credentials.getDefaultInstance()
override suspend fun readFrom(input: InputStream): Credentials =
withContext(Dispatchers.IO) {
try {
val result = Credentials.parseFrom(
streamingAead.newDecryptingStream(input, AAD)
)
Log.d(TAG, "Credentials decrypted successfully — isOnboarded: ${result.isOnboarded}")
result
} catch (e: Exception) {
Log.e(TAG, "Decryption failed — DataStore may be corrupt or key rotated", e)
throw CorruptionException("Cannot read/decrypt credentials DataStore", e)
}
}
override suspend fun writeTo(t: Credentials, output: OutputStream): Unit =
withContext(Dispatchers.IO) {
try {
val encryptingStream = streamingAead.newEncryptingStream(output, AAD)
t.writeTo(encryptingStream) // returns Int — discarded by Unit return type
encryptingStream.close()
Log.d(TAG, "Credentials encrypted and written — isOnboarded: ${t.isOnboarded}, " +
"hasInvoiceKey: ${t.invoiceKey.isNotBlank()}, " +
"hasAdminKey: ${t.adminKey.isNotBlank()}, " +
"hasBaseUrl: ${t.baseUrl.isNotBlank()}")
} catch (e: Exception) {
Log.e(TAG, "Encryption/write failed", e)
throw e
}
}
companion object {
private val AAD = "credentials_store".toByteArray(Charsets.UTF_8)
}
}