转载请注明出处:http://blog.youkuaiyun.com/wl9739/article/details/52444671
评论中很多朋友反映,根据我给出的方案,拿不到指纹信息这个问题,在这里统一说明一下。
首先,这篇文章中涉及到的代码,我在一部魅族手机和一部三星手机上进行测试过,能获取到信息。其他手机机型我没有测试,不知道详细情况。
其次,我在博客中也说明了,在不同手机厂商的定制系统里面获取到的指纹信息很可能是不同的,我测试的魅族手机和三星手机返回的信息格式就不一样。按照本文的方法获取到的指纹信息是一个比较鸡肋的功能,作用有限,我目前也没有能力给出一个完美的解决方案,如果有哪位找到了完美的解决方案,欢迎分享。
另外,指纹信息相关 API 是用 @hide 修饰的,这说明 Google 官方是不希望开发者使用这类 API ,使用这类 API 可能会有风险,如方法参数改变、在后续版本中被移除等等。
因此,对于指纹识别这一块,建议读者使用本文中提及的指纹识别功能,尽可能避免使用本文后面提及的“获取指纹信息”这一功能。
最近项目需要使用到指纹识别的功能,查阅了相关资料后,整理成此文。
指纹识别是在Android 6.0之后新增的功能,因此在使用的时候需要先判断用户手机的系统版本是否支持指纹识别。另外,实际开发场景中,使用指纹的主要场景有两种:
- 纯本地使用。即用户在本地完成指纹识别后,不需要将指纹的相关信息给后台。
- 与后台交互。用户在本地完成指纹识别后,需要将指纹相关的信息传给后台。
由于使用指纹识别功能需要一个加密对象(CryptoObject)该对象一般是由对称加密或者非对称加密获得。上述两种开发场景的实现大同小异,主要区别在于加密过程中密钥的创建和使用,一般来说,纯本地的使用指纹识别功能,只需要对称加密即可;而与后台交互则需要使用非对称加密:将私钥用于本地指纹识别,识别成功后将加密信息传给后台,后台开发人员用公钥解密,以获得用户信息。
下面先简单介绍一下对称加密和非对称加密的相关概念,然后对两种开发方式的实现分别进行讲解。
对称加密、非对称加密和签名
在正式使用指纹识别功能之前,有必要先了解一下对称加密和非对称加密的相关内容。
对称加密:所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。算法是一组规则,规定如何进行加密和解密。因此加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要。因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。
非对称加密:非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。
签名:在信息的后面再加上一段内容,可以证明信息没有被修改过。一般是对信息做一个hash计算得到一个hash值,注意,这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。在把信息发送出去时,把这个hash值加密后做为一个签名和信息一起发出去。
由以上内容可以了解到,对称加密和非对称加密的特点如下:
- 对称加密的优点是速度快,适合于本地数据和本地数据库的加密,安全性不如非对称加密。常见的对称加密算法有DES、3DES、AES、Blowfish、IDEA、RC5、RC6。
- 非对称加密的安全性比较高,适合对需要网络传输的数据进行加密,速度不如对称加密。非对称加密应用于SSH, HTTPS, TLS,电子证书,电子签名,电子身份证等等
指纹识别的对称加密实现
使用指纹识别的对称加密功能的主要流程如下:
- 使用 KeyGenerator 创建一个对称密钥,存放在 KeyStore 里。
- 设置
KeyGenParameterSpec.Builder.setUserAuthenticationRequired()
为true, - 使用创建好的对称密钥初始化一个Cipher对象,并用该对象调用
FingerprintManager.authenticate()
方法启动指纹传感器并开始监听。 - 重写
FingerprintManager.AuthenticationCallback
的几个回调方法,以处理指纹识别成功(onAuthenticationSucceeded()
)、失败(onAuthenticationFailed()
和onAuthenticationError()
)等情况。
创建密钥
创建密钥要涉及到两个类:KeyStore 和 KeyGenerator。
KeyStore 是用于存储、获取密钥(Key)的容器,获取 KeyStore的方法如下:
try {
mKeyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (KeyStoreException e) {
throw new RuntimeException("Failed to get an instance of KeyStore", e);
}
而生成 Key,如果是对称加密,就需要 KeyGenerator 类。获取一个 KeyGenerator 对象比较简单,方法如下:
// 对称加密, 创建 KeyGenerator 对象
try {
mKeyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
}
获得 KeyGenerator 对象后,就可以生成一个 Key 了:
try {
keyStore.load(null);
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(defaultKeyName,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(Key