android指纹识别开发公司,FingerDemo实现Android指纹识别
FingerDemo
指纹识别
最近在研究android的指纹,因为做的项目是金融类,所有想要把指纹添加到项目中, 但是Android手机有很多种类,有些有指纹,有些没有指纹。这就需要各种判断了。
1、判断当前设备的SDK版本 因为设备指纹是在android6.0以后才出来的,所以我们首先要判断一下SDK版本是否>=23
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
大于22
}
2、判断当前设备是否支持指纹 指纹识别肯定要求设备上有指纹识别的硬件,判断起来也简单
public static boolean isHardWareDetected(Context context) {
return FingerprintManagerCompat.from(context).isHardwareDetected();
}
3、判断当前设备是否有图案锁 这个有的一聊,Android在设置指纹时,G爹要求必须要有图案锁 ,可以是password,PIN或者图案都行 google原生的逻辑就是:想要使用指纹识别的话,必须首先使能屏幕锁才行
public static boolean isKeyguardSecure(Context context) {
return ((KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE)).isKeyguardSecure();
}
4、判断是否设置过指纹
public static boolean hasEnrolledFingerPrint(Context context) {
return FingerprintManagerCompat.from(context).hasEnrolledFingerprints();
}
根据项目需求,以上设置判断完成以后就可以调用设备指纹了, 调用指纹的方法很简单
authenticate(crypto, flags, cancel, callback, handler) 现在我们挨个解释一下这些参数都是什么:
1、crypto:这个参数加密类的对象,指纹扫描器会根据它判断认证结果的合法性,如果设置了为Null,那么手机中只要包含了录入的指纹就可以解锁成功,如果放在了金融类里面 你的账户 可以被多个设置过指纹的人使用,太坑爹了。如果不设置为Null的话,内容比较多,后面会讲
2、cancel:这个是CancellationSignal类的一个对象,这个对象是用来取消指纹操作的,建设不要设置为null,代码有中使用。
3、flags :标识位,根据图的文档描述,这个位暂时应该为0,这个标志位应该是保留将来使用的。
4、callback :这个就太重要了, 这个是指纹的回调参数,包含了成功,失败,异常等等。
5、handler:没什么用可以设置为Null
接下来进行细致的分析:
1、CryptoObject对象 首先,指纹识别的安全性就取决于这个对象 。最不愿看到的是录入指纹的时候被第三方攻击 FingerprintManager.CryptoObject是基于Java加密API的一个包装类 FingerprintManager用来保证认证结果的完整性。通常来讲,用来加密指纹扫描结果的机制就是一个Javax.Crypto.Cipher对象。Cipher对象本身会使用由应用调用Android keystore的API产生一个key来实现上面说道的保护功能。 讲这么多没用的,直接上代码
public class CryptoObjectHelper { // This can be key name you want. Should be unique for the app. static final String KEY_NAME = "com.meng.android.sample.fingerprint_authentication_key";
// We always use this keystore on Android.
static final String KEYSTORE_NAME = "AndroidKeyStore";
// Should be no need to change these values.
static final String KEY_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
static final String TRANSFORMATION = KEY_ALGORITHM + "/" +
BLOCK_MODE + "/" +
ENCRYPTION_PADDING;
final KeyStore _keystore;
public CryptoObjectHelper() throws Exception {
_keystore = KeyStore.getInstance(KEYSTORE_NAME);
_keystore.load(null);
}
public FingerprintManagerCompat.CryptoObject buildCryptoObject() throws Exception {
Cipher cipher = createCipher(true);
return new FingerprintManagerCompat.CryptoObject(cipher);
}
Cipher createCipher(boolean retry) throws Exception {
Key key = GetKey();
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
try {
cipher.init(Cipher.ENCRYPT_MODE | Cipher.DECRYPT_MODE, key);
} catch (KeyPermanentlyInvalidatedException e) {
_keystore.deleteEntry(KEY_NAME);
if (retry) {
createCipher(false);
} else {
throw new Exception("Could not create the cipher for fingerprint authentication.", e);
}
}
return cipher;
}
Key GetKey() throws Exception {
Key secretKey;
if (!_keystore.isKeyEntry(KEY_NAME)) {
CreateKey();
}
secretKey = _keystore.getKey(KEY_NAME, null);
return secretKey;
}
void CreateKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM, KEYSTORE_NAME);
KeyGenParameterSpec keyGenSpec =
new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(BLOCK_MODE)
.setEncryptionPaddings(ENCRYPTION_PADDING)
.setUserAuthenticationRequired(true)
.build();
keyGen.init(keyGenSpec);
keyGen.generateKey();
}
}
1、上面的类会针对每个CryptoObject对象都会新建一个Cipher对象,并且会使用由应用生成的key
2、这个key的名字是使用KEY_NAME变量定义的,这个名字应该是保证唯一的,建议使用APPID区别
3、GetKey方法会尝试使用Android Keystore的API来解析一个key(名字就是上面我们定义的),如果key不存在的话,那就调用CreateKey方法新建一个key。
4、cipher变量的实例化是通过调用Cipher.getInstance方法获得的,这个方法接受一个transformation参数,这个参数制定了数据怎么加密和解密。然后调用Cipher.init方法就会使用应用的key来完成cipher对象的实例化工作。
接下来这个Key会在Android中认为无效的地方有:
1、添加一个新的指纹
2、当前设备中曾经的指纹不存在了,或全部删除
3、用户关了屏幕锁功能
4、用户更换了屏幕锁方法,如password改成PIN或者图案方式
以上的情况Cipher.init方法都会抛出KeyPermanentlyInvalidatedException的异常,上面我的代码中捕获了这个异常,并且删除了当前无效的key,然后根据参数尝试再次创建。
接下来看CreateKey()这个方法:
1、KeyGenerator类会创建一个key,但是需要一些原始数据才能创建key,这些原始的信息是通过KeyGenParameterSpec类的对象来提供的。
2、用它的工厂方法getInstance进行的,从上面的代码中我们可以看到这里使用的AES(Advanced Encryption Standard )加密算法的,AES会将数据分成几个组,然后针对几个组进行加密。
接下来,KeyGenParameterSpec的实例化是使用它的Builder方法:
1、KEY_NAME:key的名字
2、KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT:key必须在加密和解密的时候是有效的
3、setBlockModes(BLOCK_MODE):一个被AES切分的数据块都与之前的数据块进行了异或运算了,这样的目的就是为了建立每个数据块之间的依赖关系。
4、setEncryptionPaddings(ENCRYPTION_PADDING):这个是上面的常量,表示使用了PKSC7(Public Key Cryptography Standard #7)的方式去产生用于填充AES数据块的字节,这样就是要保证每个数据块的大小是等同的
5、setUserAuthenticationRequired(true):调用意味着在使用key之前用户的身份需要被认证。
每次KeyGenParameterSpec创建的时候,他都被用来初始化KeyGenerator,这个对象会产生存储在设备上的key。
最后就是最主要的callback回调了
1、onAuthenticationError:验证出错回调 指纹传感器会关闭一段时间,在下次调用authenticate时,会出现禁用期(时间依厂商不同30,1分都有)
这个接口会再系统指纹认证出现不可恢复的错误的时候才会调用,并且参数errorCode就给出了错误码,标识了错误的原因。
这个时候app能做的只能是提示用户重新尝试一遍。
2、onAuthenticationHelp:验证帮助回调
3、onAuthenticationSucceeded:成功回调
CryptoObject不是null的话,那么我们在这个方法中可以通过AuthenticationResult来获得Cypher对象然后调用它的doFinal方法。
doFinal方法会检查结果是不是会拦截或者篡改过,如果是的话会抛出一个异常。
当我们发现这些异常的时候都应该将认证当做是失败来来处理
4、onAuthenticationFailed:失败回调
以上内容就是调用Android指纹的内容,总体来说不多。
这时候是时候抛出一个问题了,如果我们也想向微信那们做一个指纹支付,那是不是就应该是唯一的指纹和密码绑定在一起。 因为不可能是多个指纹都可以用来进行支付,就像上面说到的,一个账户可以被多个指纹进行支付,如果是你朋友不小心用你手机绑了一个指纹,那么。。。 所以我们如果进行指纹和密码绑定,有人说既然设置了指纹就肯定会有指纹Id,用唯一的指纹Id和密码绑定在一起不就好了。 哇,这个想法简单完美,拿到指纹Id这事不就全解决了吗,但是指纹Id真的就这么好拿吗。。
实不相瞒:
1、AuthenticationResult这个对象是在callback成功回调里拿到的。 这个对象里面就有fingerId但是被@hide修饰了,拿不到了。。。
2、直接拿不到,我用反射拿不就行了,你会发现就算通过反射来拿Fingerprint对象,拿到的也是null.....
3、StackOverflow上也有人提出相同的问题:Fingerprint为null,他是直接把android.jar包换了。换成了这里没有@hide修饰了。这样就可以直接在代码里面使用,但是拿到的也是null。
这么多办法就是拿不到怎么办。
真拿不到啊,我也没有办法。
这个玩意可以拿到:Tencent/soter github上面有~~但是还没有研究它是怎么拿到了, 我得继续看了。
android指纹识别开发公司,FingerDemo实现Android指纹识别相关推荐
- 实现Android底层驱动开发并裁剪定制Android操作系统
毕业论文 题 目实现Android底层驱动开发并裁剪定制Android操作系统 学 院电子信息与电气工程学院 姓 名牛xxx民 专 业电子信息科学与技术 学 号2012xxxxxx ...
- Android车载应用开发与分析 - 车载Android应用开发入门指南
1. 前言 - 移动互联网退潮下的汽车大战 2019年中国首个外商独资的整车制造项目,"上海特斯拉超级工厂"开工了. 特斯拉在智能化和电子化上的巨大优势将智能汽车推向了一个全新的高 ...
- android 添加ga_android开发步步为营之70:android接入Google Analytics总结
求人不如求己,今天项目里要接入Google Analytics,这个是做应用统计分析用的,可以查看当前手机活跃用户,事件点击等等数据,先看看效果: 之前eclipse里面接入已经成功,昨天项目组决定项 ...
- android系统nfc开发,GitHub - hanjie511/MyNFC: android的NFC开发入门
MyNFC android的NFC开发入门 NFC简述 近距离无线通信 (NFC) 是一组近距离无线技术,通常只有在距离不超过 4 厘米时才能启动连接.借助 NFC,您可以在 NFC 标签与 Andr ...
- android另类工具,[置顶] android应用程序开发另解及Android SDK工具集的另类用法
转载请注明出处: LouisWang http://blog.csdn.net/louiswangbing/article/details/6606865 相信对于广大Android应用开发爱好者来说 ...
- Android NDK jni开发,适当的给Android 代码加密
为什么使用ndk开发了,就是 稍微将代码隐藏一下..Android 虽然打包能混淆,但是有些东西是不能混淆的,如下图,压缩密码把直勾勾的下载代码中.下面手把手稍微优化下. 將操作密码的部分我们通过 j ...
- Android学习1——开发环境搭建、Android Studio安装
一.目的 1.掌握 Android 开发环境搭建方法 2.掌握 Android 项目建立方法 3.掌握 Gitee 账号建立及其使用方法 4.掌握 Android 模拟器使用方法 二.实验环境 1.J ...
- 小米5怎样升级android,小米5开发版怎么升级Android 7.0?小米5开发版升级Android 7.0教程...
Android 7.0系统已经陆续推送,今天小米5手机的Android 7.0终于公测了,虽然只限于开发版,但是小伙伴们总算有盼头了!小米5开发版怎么升级Android 7.0?下面小编为大家带来小米 ...
- 记一次Android全流程开发体验经历以及Android Studio使用【从环境搭建到项目打包发布 + 真实踩坑总结】
前言 临时安排接手一个 Android 应用项目开发,庆幸的是 Android APP 已经开发完成,我只需要在我的电脑上运行起来打包看一下效果即可,但是对于一个从未接触过安卓开发的我来说真的是费尽脑 ...
最新文章
- 又爱又恨的 Microsoft Edge!
- 12月第1周.BIZ域名总量TOP10:仅中德澳3国持续上涨
- JStorm与Storm源码分析(一)--nimbus-data
- IE报vuex requires a Promise polyfill in this browser问题解决
- np.c_与np.r_
- git clone 所有远程分支
- 分层架构web容器的配置安全
- 增大表名最大长度_风电叶片材料的发展变迁史,及风力发电机叶片长度发展历程...
- 14天1000+大集群滚动升级,银行柜台竟然毫无感觉
- 数据分析技术 使用SQL和EXCEL工具 第2版 pdf
- python新手图解_Python完全新手教程
- VMware Workstation Pro 16序列号
- go 的基本命令详解
- 常见随机变量的数学期望和方差
- python的彪悍特性--自省
- 云和恩墨校园猎手招募令
- idea自动生成bean实体对象
- Linux的时区修改方法
- 电商类产品搜索功能如何优化?
- Centos7安装MySQL初始化缺少libaio.so.1
热门文章
- php DHT22,很奇怪,IDE版本导致DHT22输出异常
- RATIONAL ROSE 2007详细安装教程(图文版)
- jpa中的表关系以及多表CRUD操作
- 汽车发动机进气温度传感器和氧传感器原理
- matlab膨胀检测,matlab腐蚀膨胀算法
- 采集数据用云服务器与公司网站,网络爬虫软件,企业版,大企业,采集内网数据,私有云部署-集搜客GooSeeker...
- 018-JVM-class文件的形象表示
- groupby 的妙用(注意size和count)
- 创新工场汪华:为什么移动互联网的机会是互联网的十倍?
- 掌握自动化测试必要的几种技能?