Files
gudari/app/src/main/java/com/bitcointxoko/gudariwallet/security/SecretManager.kt
T
2026-06-01 03:09:19 +02:00

59 lines
2.4 KiB
Kotlin

package com.bitcointxoko.gudariwallet.security
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.GCMParameterSpec
import android.util.Base64
object SecretManager {
private const val KEY_ALIAS = "lnbits_api_key"
private const val KEYSTORE_PROVIDER = "AndroidKeyStore"
private const val TRANSFORMATION = "AES/GCM/NoPadding"
private const val GCM_TAG_LENGTH = 128
/** Generate (or retrieve) the AES key in the Keystore */
private fun getOrCreateKey(): SecretKey {
val keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER).apply { load(null) }
keyStore.getKey(KEY_ALIAS, null)?.let { return it as SecretKey }
val keyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER)
keyGen.init(
KeyGenParameterSpec.Builder(
KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(256)
// Require device lock screen to be set up
.setUserAuthenticationRequired(false)
.build()
)
return keyGen.generateKey()
}
/** Encrypt a plaintext string; returns Base64(IV + ciphertext) */
fun encrypt(plaintext: String): String {
val cipher = Cipher.getInstance(TRANSFORMATION)
cipher.init(Cipher.ENCRYPT_MODE, getOrCreateKey())
val iv = cipher.iv
val ciphertext = cipher.doFinal(plaintext.toByteArray(Charsets.UTF_8))
val combined = iv + ciphertext
return Base64.encodeToString(combined, Base64.DEFAULT)
}
/** Decrypt a Base64(IV + ciphertext) string */
fun decrypt(encoded: String): String {
val combined = Base64.decode(encoded, Base64.DEFAULT)
val iv = combined.copyOfRange(0, 12)
val ciphertext = combined.copyOfRange(12, combined.size)
val cipher = Cipher.getInstance(TRANSFORMATION)
cipher.init(Cipher.DECRYPT_MODE, getOrCreateKey(), GCMParameterSpec(GCM_TAG_LENGTH, iv))
return String(cipher.doFinal(ciphertext), Charsets.UTF_8)
}
}