bitsy-wallet/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/CryptoUtils.kt

99 lines
3.0 KiB
Kotlin

package cy.agorise.bitsybitshareswallet.utils
import android.content.Context
import android.util.Base64
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.moldedbits.r2d2.R2d2
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
import javax.crypto.AEADBadTagException
/**
* Class that provides encryption/decryption support by using the key management framework provided
* by the KeyStore system.
*
* The implemented scheme was taken from [this](https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3)> blog post.
*
* @see [Android Keystore System](https://developer.android.com/training/articles/keystore.html)
*/
object CryptoUtils {
/**
* Encrypts and stores a key-value pair in the shared preferences
* @param context The application context
* @param key The key to be used to reference the data
* @param value The actual value to be stored
*/
fun put(context: Context, key: String, value: String) {
val r2d2 = R2d2(context)
val encrypted = r2d2.encryptData(value)
PreferenceManager.getDefaultSharedPreferences(context).edit {
putString(key, encrypted)
}
}
/**
* Retrieves and decrypts an encrypted value from the shared preferences
* @param context The application context
* @param key The key used to reference the data
* @return The plaintext version of the encrypted data
*/
operator fun get(context: Context, key: String): String {
val r2d2 = R2d2(context)
val encrypted = PreferenceManager.getDefaultSharedPreferences(context).getString(key, null)
return r2d2.decryptData(encrypted)
}
/**
* Encrypts some data
* @param context The application context
* @param plaintext The plaintext version of the data
* @return Encrypted data
*/
fun encrypt(context: Context, plaintext: String): String {
val r2d2 = R2d2(context)
return r2d2.encryptData(plaintext)
}
/**
* Decrypts some data
* @param context The application context
* @param ciphertext The ciphertext version of the data
* @return Decrypted data
*/
@Throws(AEADBadTagException::class)
fun decrypt(context: Context, ciphertext: String): String {
val r2d2 = R2d2(context)
return r2d2.decryptData(ciphertext)
}
/**
* Generates a random salt string
*/
fun generateSalt(): String {
val salt = ByteArray(16)
SecureRandom().nextBytes(salt)
return Base64.encodeToString(salt, Base64.DEFAULT).trim()
}
/**
* Creates a SHA-256 hash of the given string
*/
@Throws(NoSuchAlgorithmException::class)
fun createSHA256Hash(text: String): String {
val md = MessageDigest.getInstance("SHA-256")
md.update(text.toByteArray())
val digest = md.digest()
return Base64.encodeToString(digest, Base64.DEFAULT).trim()
}
}