55 lines
2.1 KiB
Kotlin
55 lines
2.1 KiB
Kotlin
package com.longnh15.heimdall.common
|
|
|
|
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 kotlin.io.encoding.Base64
|
|
|
|
object TokenCrypto {
|
|
private const val PROVIDER = "AndroidKeyStore"
|
|
private const val ALIAS = "auth_token_key"
|
|
private const val TRANSFORMATION = "AES/GCM/NoPadding"
|
|
private const val IV_SIZE = 12
|
|
private const val TAG_BITS = 128
|
|
|
|
private val keystore = KeyStore.getInstance(PROVIDER).apply { load(null) }
|
|
|
|
private fun getOrCreateKey(): SecretKey {
|
|
(keystore.getEntry(ALIAS, null) as? KeyStore.SecretKeyEntry)?.let {
|
|
return it.secretKey
|
|
}
|
|
val keyGen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, PROVIDER)
|
|
keyGen.init(
|
|
KeyGenParameterSpec.Builder(
|
|
ALIAS,
|
|
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
|
|
)
|
|
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
|
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
|
.setKeySize(256)
|
|
.build()
|
|
)
|
|
return keyGen.generateKey()
|
|
}
|
|
|
|
fun encrypt(plainText: String): String {
|
|
val cipher = Cipher.getInstance(TRANSFORMATION)
|
|
cipher.init(Cipher.ENCRYPT_MODE, getOrCreateKey())
|
|
val iv = cipher.iv // 12-byte IV, generated by Keystore
|
|
val cipherText = cipher.doFinal(plainText.toByteArray(Charsets.UTF_8))
|
|
return Base64.encode(iv + cipherText) // prepend IV
|
|
}
|
|
|
|
fun decrypt(encoded: String): String {
|
|
val combined = Base64.decode(encoded)
|
|
val iv = combined.copyOfRange(0, IV_SIZE)
|
|
val cipherText = combined.copyOfRange(IV_SIZE, combined.size)
|
|
val cipher = Cipher.getInstance(TRANSFORMATION)
|
|
cipher.init(Cipher.DECRYPT_MODE, getOrCreateKey(), GCMParameterSpec(TAG_BITS, iv))
|
|
return cipher.doFinal(cipherText).toString(Charsets.UTF_8)
|
|
}
|
|
} |