您好,我正在尝试使用指纹和个人密码访问我的android应用程序。我使用Cipher
加密数据。我将加密的密码存储在SharedPreferences
中。我可以使用指纹解密密码,但是如果手动输入密码,则无法解密密码。我的意思是,我在EditText
中输入密码,并尝试将其与SharedPreferences
中的加密密码进行比较。
CryptoUtils类:
@TargetApi(Build.VERSION_CODES.M)
object CryptoUtils {
private val TAG = CryptoUtils::class.java.simpleName
private val KEY_ALIAS = "key_for_pin"
private val KEY_STORE = "AndroidKeyStore"
private val TRANSFORMATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"
private var sKeyStore: KeyStore? = null
private var sKeyPairGenerator: KeyPairGenerator? = null
private var sCipher: Cipher? = null
private val keyStore: Boolean
get() {
try {
sKeyStore = KeyStore.getInstance(KEY_STORE)
sKeyStore!!.load(null)
return true
} catch (e: KeyStoreException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: CertificateException) {
e.printStackTrace()
}
return false
}
private val keyPairGenerator: Boolean
@TargetApi(Build.VERSION_CODES.M)
get() {
try {
sKeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, KEY_STORE)
return true
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: NoSuchProviderException) {
e.printStackTrace()
}
return false
}
private val cipher: Boolean
@SuppressLint("GetInstance")
get() {
try {
sCipher = Cipher.getInstance(TRANSFORMATION)
return true
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: NoSuchPaddingException) {
e.printStackTrace()
}
return false
}
private val key: Boolean
get() {
try {
return sKeyStore!!.containsAlias(KEY_ALIAS) || generateNewKey()
} catch (e: KeyStoreException) {
e.printStackTrace()
}
return false
}
val cryptoObject: FingerprintManagerCompat.CryptoObject?
@Nullable
get() = if (prepare() && initCipher(Cipher.DECRYPT_MODE)) {
FingerprintManagerCompat.CryptoObject(sCipher!!)
} else null
fun encode(inputString: String): String? {
try {
if (prepare() && initCipher(Cipher.ENCRYPT_MODE)) {
val bytes = sCipher!!.doFinal(inputString.toByteArray())
return Base64.encodeToString(bytes, Base64.NO_WRAP)
}
} catch (exception: IllegalBlockSizeException) {
exception.printStackTrace()
} catch (exception: BadPaddingException) {
exception.printStackTrace()
}
return null
}
fun decode(encodedString: String, cipher: Cipher): String? {
try {
val bytes = Base64.decode(encodedString, Base64.NO_WRAP)
return String(cipher.doFinal(bytes))
} catch (exception: IllegalBlockSizeException) {
exception.printStackTrace()
} catch (exception: BadPaddingException) {
exception.printStackTrace()
}
return null
}
private fun prepare(): Boolean {
return keyStore && cipher && key
}
@TargetApi(Build.VERSION_CODES.M)
private fun generateNewKey(): Boolean {
if (keyPairGenerator) {
try {
sKeyPairGenerator!!.initialize(
KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.setUserAuthenticationRequired(true)
.build())
sKeyPairGenerator!!.generateKeyPair()
return true
} catch (e: InvalidAlgorithmParameterException) {
e.printStackTrace()
}
}
return false
}
private fun initCipher(mode: Int): Boolean {
try {
sKeyStore!!.load(null)
when (mode) {
Cipher.ENCRYPT_MODE -> initEncodeCipher(mode)
Cipher.DECRYPT_MODE -> initDecodeCipher(mode)
else -> return false //this cipher is only for encode\decode
}
return true
} catch (exception: KeyPermanentlyInvalidatedException) {
deleteInvalidKey()
} catch (e: KeyStoreException) {
e.printStackTrace()
} catch (e: CertificateException) {
e.printStackTrace()
} catch (e: UnrecoverableKeyException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: InvalidKeyException) {
e.printStackTrace()
} catch (e: InvalidKeySpecException) {
e.printStackTrace()
} catch (e: InvalidAlgorithmParameterException) {
e.printStackTrace()
}
return false
}
@Throws(KeyStoreException::class, NoSuchAlgorithmException::class, UnrecoverableKeyException::class, InvalidKeyException::class)
private fun initDecodeCipher(mode: Int) {
val key = sKeyStore!!.getKey(KEY_ALIAS, null) as PrivateKey
sCipher!!.init(mode, key)
}
@Throws(KeyStoreException::class, InvalidKeySpecException::class, NoSuchAlgorithmException::class, InvalidKeyException::class, InvalidAlgorithmParameterException::class)
private fun initEncodeCipher(mode: Int) {
val key = sKeyStore!!.getCertificate(KEY_ALIAS).publicKey
// workaround for using public key
// from https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.html
val unrestricted = KeyFactory.getInstance(key.getAlgorithm()).generatePublic(X509EncodedKeySpec(key.getEncoded()))
// from https://code.google.com/p/android/issues/detail?id=197719
val spec = OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT)
sCipher!!.init(mode, unrestricted, spec)
}
fun deleteInvalidKey() {
if (keyStore) {
try {
sKeyStore!!.deleteEntry(KEY_ALIAS)
} catch (e: KeyStoreException) {
e.printStackTrace()
}
}
}
}
FingerprintUtils类:
enum class SensorState {
NOT_SUPPORTED,
NOT_BLOCKED,
NO_FINGERPRINTS,
READY
}
fun checkFingerprintCompatibility(context: Context): Boolean {
return FingerprintManagerCompat.from(context).isHardwareDetected
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
fun checkSensorState(context: Context): SensorState {
if (checkFingerprintCompatibility(context)) {
val keyguardManager =
context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (!keyguardManager.isKeyguardSecure) {
return SensorState.NOT_BLOCKED
}
return if (!FingerprintManagerCompat.from(context).hasEnrolledFingerprints()) {
SensorState.NO_FINGERPRINTS
} else SensorState.READY
} else {
return SensorState.NOT_SUPPORTED
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
fun isSensorStateAt(state: SensorState, context: Context): Boolean {
return checkSensorState(context) == state
}
我在FingerPrintHelper
中使用的 Activity
类:
class FingerprintHelper(private val mContext: Context, private val etPincode: PinField) : FingerprintManagerCompat.AuthenticationCallback() {
private var mCancellationSignal: CancellationSignal? = null
internal fun startAuth(cryptoObject: FingerprintManagerCompat.CryptoObject) {
mCancellationSignal = CancellationSignal()
val manager = FingerprintManagerCompat.from(mContext)
manager.authenticate(cryptoObject, 0, mCancellationSignal, this, null)
}
internal fun cancel() {
if (mCancellationSignal != null) {
mCancellationSignal!!.cancel()
}
}
override fun onAuthenticationError(errMsgId: Int, errString: CharSequence?) {
Toast.makeText(mContext, errString, Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationHelp(helpMsgId: Int, helpString: CharSequence?) {
Toast.makeText(mContext, helpString, Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationSucceeded(result: FingerprintManagerCompat.AuthenticationResult?) {
val cipher = result!!.cryptoObject.cipher
val encoded = PasswordStorage.getPasswordCode()
val decoded = CryptoUtils.decode(encoded!!, cipher!!)
etPincode.setText(decoded)
Toast.makeText(mContext, "success", Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationFailed() {
Toast.makeText(mContext, "try again", Toast.LENGTH_SHORT).show()
}
}
指纹完美工作。它从SharedPreferences
解密我的密码。
但是,如何在没有指纹的情况下手动解密呢?
答案 0 :(得分:0)
我将加密一个加盐密码并将其(作为SHA256)存储在Android偏好设置中,然后当用户输入密码时,我将再次对该密码进行加密并检查SHA256的乘积是否相同。< / p>