security: encrypt credentials, caches, and harden lock screen

This commit is contained in:
2026-05-15 18:35:14 +05:00
parent 106004421e
commit fc031f1f2a
20 changed files with 506 additions and 149 deletions
@@ -12,8 +12,10 @@ import androidx.fragment.app.Fragment
import com.google.android.material.button.MaterialButton
import sh.sar.basedbank.R
import sh.sar.basedbank.databinding.FragmentSecuritySetupBinding
import java.security.MessageDigest
import sh.sar.basedbank.util.CredentialStore
import java.security.SecureRandom
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.PBEKeySpec
class SecuritySetupFragment : Fragment() {
@@ -231,16 +233,25 @@ class SecuritySetupFragment : Fragment() {
private fun saveCredential(method: String, input: String) {
val salt = ByteArray(16).also { SecureRandom().nextBytes(it) }
val saltB64 = Base64.encodeToString(salt, Base64.NO_WRAP)
val hash = sha256(saltB64 + input)
val hash = pbkdf2(input, salt)
requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE).edit()
.putString("security_method", method)
.putString("security_salt", saltB64)
.putString("security_hash", hash)
// Remove legacy plaintext fields if they exist from an old install
.remove("security_salt")
.remove("security_hash")
.apply()
CredentialStore(requireContext()).saveSecurityHash(saltB64, hash)
}
private fun sha256(input: String) = MessageDigest.getInstance("SHA-256")
.digest(input.toByteArray()).joinToString("") { "%02x".format(it) }
private fun pbkdf2(input: String, salt: ByteArray): String {
val spec = PBEKeySpec(input.toCharArray(), salt, 100_000, 256)
return try {
val hash = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(spec).encoded
Base64.encodeToString(hash, Base64.NO_WRAP)
} finally {
spec.clearPassword()
}
}
private fun finishSetup() {
val cb = activity as? Callback