使用指纹和别针

时间:2019-01-17 12:53:55

标签: android encryption kotlin fingerprint

您好,我正在尝试使用指纹和个人密码访问我的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解密我的密码。 但是,如何在没有指纹的情况下手动解密呢?

1 个答案:

答案 0 :(得分:0)

我将加密一个加盐密码并将其(作为SHA256)存储在Android偏好设置中,然后当用户输入密码时,我将再次对该密码进行加密并检查SHA256的乘积是否相同。< / p>