54 lines
2.1 KiB
Kotlin
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)
|
|
}
|
|
}
|