exporting credentials now requires a password (encrypted)

This commit is contained in:
rebelonion 2024-02-02 16:45:07 -06:00
parent ed6275b0e8
commit 2214c47c0c
6 changed files with 228 additions and 26 deletions

View file

@ -90,7 +90,7 @@ object PrefManager {
}
@Suppress("UNCHECKED_CAST")
fun <T> getNullableVal(prefName: PrefName, default: T?) : T? {
fun <T> getNullableVal(prefName: PrefName, default: T?) : T? { //Strings don't necessarily need to use this one
return try {
val pref = getPrefLocation(prefName.data.prefLocation)
when (prefName.data.type) {
@ -254,7 +254,7 @@ object PrefManager {
}
@Suppress("UNCHECKED_CAST")
fun importAllPrefs(prefs: Map<String, *>, prefLocation: Location) {
fun importAllPrefs(prefs: Map<String, *>, prefLocation: Location): Boolean {
val pref = getPrefLocation(prefLocation)
var hadError = false
pref.edit().clear().apply()
@ -273,8 +273,13 @@ object PrefManager {
}
}
apply()
if (hadError) snackString("Error importing preferences")
else snackString("Preferences imported")
return if (hadError) {
snackString("Error importing preferences")
false
} else {
snackString("Preferences imported")
true
}
}
}

View file

@ -0,0 +1,61 @@
package ani.dantotsu.settings.saving.internal
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.PBEKeySpec
//used to encrypt and decrypt json strings on import and export
class PreferenceKeystore {
companion object {
fun generateKey(alias: String) {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
keyGenerator.init(
KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setRandomizedEncryptionRequired(false)
.build()
)
keyGenerator.generateKey()
}
fun encryptWithPassword(password: CharArray, plaintext: String, salt: ByteArray): ByteArray {
val secretKey = deriveKeyFromPassword(password, salt)
val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16)))
return cipher.doFinal(plaintext.toByteArray(Charsets.UTF_8))
}
fun decryptWithPassword(password: CharArray, ciphertext: ByteArray, salt: ByteArray): String {
val secretKey = deriveKeyFromPassword(password, salt)
val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16))) // Use the correct IV
return cipher.doFinal(ciphertext).toString(Charsets.UTF_8)
}
fun generateSalt(): ByteArray {
val random = SecureRandom()
val salt = ByteArray(16)
random.nextBytes(salt)
return salt
}
private fun deriveKeyFromPassword(password: CharArray, salt: ByteArray): SecretKey {
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val spec = PBEKeySpec(password, salt, 10000, 256)
return factory.generateSecret(spec)
}
}
}