现在指纹登录是一种很常见的登录方式,特别是在金融类APP中,使用指纹进行登录、支付的特别多。指纹登录本身是一种指纹身份认证技术,通过识别当前用户的指纹信息,进而确认用户在系统内的注册身份。
指纹认证得以流行,我认为有两个关键点:
一是简便,没有了忘记密码的烦恼,也免去了输入密码的繁琐。
二是安全,能够用在支付环节,这就说明其可以达到金融级别的安全。
这篇文章就来简单看下指纹认证是如何做到以上两点的,其中有哪些坑,有哪些坎。
指纹识别的原理指纹认证的历史其实是很悠久的,在我国唐代指纹已经广泛应用于文书契约,宋代手印已正式成为刑事诉讼的物证,这说明人们早就认识到了个体指纹的独特性,并且有了成熟的识别方法。对于计算机指纹识别,也是去寻找指纹的独特性,这里仅做简单的介绍:
有一个关键概念:指纹特征点,常见的特征点有指纹中的端点和分叉点,算法中通常记录它们的位置和方向。程序通过光学传感器采集指纹图像,提取指纹特征点,用数学表达式描述它们,称为指纹模版。注册指纹时把指纹模版保存到数据库或其它存储中;验证指纹时,先提取当前指纹的特征点,再和已记录的指纹模版进行比对,匹配度达到一定的阈值就算匹配成功。
对于指纹识别的两个安全问题:
- 指纹图像泄漏问题:程序可以不保存指纹图像;指纹模版进行某种加密处理后,可以做到无法还原出指纹图像。当然能做和做不做是两码事。指纹泄漏还有另一种情况,2014年德国黑客从照片中成功提取了德国国防部长的指纹,所以以后拍照时不要比划剪刀手了,但是大部分人的账户应该不值得冒着巨大的风险、花费很大的力气这样搞,所以平常也不用太担心,注意下就行了。
- 假指纹识别问题:万一指纹被别人采集到了,或者制作成了指模,是不是就可以畅通无阻了呢?对应这类问题,有活体指纹检测技术。硬件上采用电容传感器采集温度、心率等数据,加上光学传感器的指纹纹路数据,进行综合判断;软件上的实现则一般通过机器学习的方式进行识别。但是两者对假指纹的识别率可能都不太理想,可见的厂商宣传也不多,其中原因可能是因为仿生技术太牛逼了,这里也没找到太多有价值的信息。实际应用在金融领域时,金融服务商必然采取了更多的手段来降低安全风险,而不是单纯地看指纹认证结果,毕竟出了问题生意可能就做不下去了,所以大规模应用时的安全风险应该是有所控制的。
在移动设备广泛采用指纹认证之前,这一技术已经得到了大范围的应用,很多人应该都接触过刷指纹的门禁或者考勤机。从老板的角度看,刷指纹比刷卡更能有效地验证员工的身份,而且成本也不高。从员工的角度看,不用多带一张卡,更方便高效。从安全的角度考虑,指纹识别技术比较成熟,只要不泄漏,一般也不会出问题,设备做得好安全性还更高一些;出问题也仅在门禁这个环节,即使没有指纹认证,也有别的方法开门,复制门禁卡或者钥匙可能更方便;对于更重要的保护对象,应该还有更安全的保护措施。
在门禁中使用指纹一般是先注册,将用户和指纹进行绑定,提取出的指纹特征数据就保存在本地,具体注册过程如下图所示:
当用户需要开门时,在指纹机上刷指纹,指纹机会提取当前指纹的特征值,然后和本地存储的指纹数据进行一一比对,如果匹配度达到一定的阈值,则指纹识别成功,向门禁下达开门指令,具体认证过程如下图所示:
APP中的指纹认证
这里说的APP指的是移动设备系统中的第三方应用,移动设备系统特指当前比较流行的Android和iOS等手机操作系统。
APP中的指纹认证目前常见于登录或者支付功能,因为涉及到APP自身的用户和业务数据操作,必然需要和APP后端服务进行交互,基于安全考虑,客户端和服务端之间也需要进行身份认证,所以APP中的指纹认证被分成了两部分:手机本地认证和远程认证。
本机认证手机系统本身的指纹认证和门禁系统中的指纹认证并无本质区别:用户首先录入指纹,基于安全考虑,指纹的特征数据也是保存在手机本地;使用指纹进入系统时也是先提取当前的特征值,然后和本地的指纹库进行比对,匹配上了就能进手机入系统。
和门禁系统不同的一点是,手机中用户需要有一个能进入系统的密码,可以是字符密码,也可以是手势密码,当用户的指纹无法使用时(可能是指纹模块故障,也可能是用户指纹问题),仍然能有其它方式进入手机;门禁系统中用户则可以只有指纹认证这一种方式,进不了门时,还可以找管理员。
当然只使用手机本地认证也是有意义的,每次APP从后台切换到前台时都需要用户刷指纹,以验证当前操作用户的身份,很多的银行APP就是这样做的(其实我并未确认这些APP此时有没有去后台再次验证,只是认为这是一种有意义的认证方式)。
本机认证的安全性手机操作系统厂商们已经做得很好了,指纹的注册和识别都在安全区域内进行,指纹识别的结果可以加密的方式返回给APP,这块直接应用就可以了。
远程认证远程认证就是客户端和服务端之间的认证,完整的方式就是双向认证:客户端要验证服务端的身份,以免被套取信息;服务端要验证客户端的身份,以免用户身份被冒充。
- 客户端验证服务端的身份:现在都使用https了,https证书就是服务端身份的保证,至少可以保证访问到地址就是你想访问的域名地址,高级点的证书还能标识证书所有者的身份;使用https时数据也是加密传输的,所以一般应用场景是没问题的。但是也发生过滥发证书的情况,所以如果需要更高的安全级别,服务端可以再生成一对非对称密钥。公钥发给APP,私钥自己保存好,每次认证时,客户端先采用服务端的公钥对数据进行加密,然后再发送出去,服务端再采用自己的私钥进行解密,如此假冒的服务端就不能解密数据,就什么也得不到;服务端返回给客户端的数据带上私钥对数据的签名,客户端可以验证签名,验证通过则代表是服务端返回的,就可以应用这些数据。
- 服务端验证客户端的身份:也是通过非对称密钥的方式,客户端生成一对非对称密钥,私钥自己保存好,公钥发送到服务端。指纹认证通过后客户端使用私钥对请求参数进行签名,然后再发送出去,服务端使用客户端公钥对接收到的数据签名进行验证,如果验证通过,则说明数据没有被篡改,可以处理客户端发起的业务请求。
这里以登录为例,来看看如何使用指纹认证来做APP登录。还是先要注册指纹,具体过程如下图所示:
- 5开启指纹:开启指纹登录的时机,一般都是先用别的方式登录了APP,然后再开启指纹登录。但是也有一些例外,用户使用APP时直接使用第三方登录,第三方提供了指纹登录的方式,比如使用Apple Id登录。上边图中是先用账号密码登录了系统,然后才开启的指纹认证。
- 12对比系统存在的指纹:指纹数据始终保存在手机本地,不会上传到远程。目前市面上的手机都是这样做的,Android和iOS提供的指纹认证API都只返回true或者false的认证结果,这样可以避免云服务被攻破时导致大规模泄漏的严重后果,最大限度的保护用户生物特征数据的安全。
- 13指纹验证成功:本地指纹认证通过就代表用户身份验证通过,不管是哪个手指。早期的操作系统版本中可能能够获得是使用的哪个指纹,但是现在一般都不开放了,只能得知指纹集是否发生了变化(删除或者添加了指纹),此时App可以强制用户退出,再使用其它安全的方式登录,然后再让用户决定是否开启指纹,支付宝就是这样做的。
- 重放攻击问题:步骤16中的请求可能被人截获,虽然无法解密,但是可以多次发向服务端,造成重放攻击的问题,可以引入一个挑战码来解决这个问题。步骤8初始化指纹注册请求时服务端可以生成这个挑战码,然后在步骤16中携带这个挑战码,然后在服务端进行验证。
下面再来看下使用指纹登录的过程:
- 登录时的本机指纹认证和注册时的本机指纹认证方法相同,只不过这次是在用户选择指纹登录时弹出指纹刷取页面。
- 10签名登录数据:主要是用客户端私钥签名设备的唯一标识和挑战码,在开启指纹认证时指定了必须采用指纹授权的方式才能使用私钥,这样能确保签名是由认证过的用户发起的(准确的说是手机上登录过指纹的所有用户,在开启指纹认证时已经提示用户所有录入的指纹都将可以用来登录,同时如果指纹发生变化,会让用户重新确认,所以可以认为他们都是有权限的用户);服务端如果验证签名通过,则代表数据在传输过程中没有被篡改,登录是在可信的客户端发起的;前后端的认证结果结合起来就代表登录是由认证过的用户发起的。
- 在开启指纹阶段,已经将设备唯一标识、客户端公钥绑定到了用户记录,所以签名验证通过后,就可以生成当前用户的登录Token,并在后续的客户端与服务端的一般交互中使用这个Token。在关键的交互,比如支付中,还是要使用指纹认证这种安全性更高的方式。
以上就是APP中的指纹认证原理,指纹登录和指纹登录的过程差不多,只不过支付需要更高的安全等级,指纹认证可以满足这个安全要求。
客户端身份认证的问题在上文APP的指纹注册阶段,客户端生成了一对非对称密钥,用于后续服务端认证客户端的身份,这个密钥在当前的手机中已经有了成熟的安全存储和使用方法,这就是TEE(可信执行环境):
客户端私钥被TEE安全密钥加密存储在手机中,目前没有破解之法;同时还可以指定只有通过了本机指纹认证才能使用私钥对数据进行签名和加密;再者如果手机中加入了新的指纹或者删除了指纹,存储的私钥就会失效;所以密钥的存储和使用是可以保证安全的。
但是还存在其它的安全隐患:
1、服务端无法确认上传的客户端公钥能否代表客户端身份,任何程序都可以生成一对非对称密钥,然后对数据进行签名,再把公钥一起发到服务端,服务端仅能验证签名的正确性,但是无法验证公钥的来源,也就无法验证客户端的身份。某些解决方案中会在客户端集成一个认证器SDK,这个SDK生成的认证信息中会携带一些特殊识别信息,而且每个应用每个机器不同,很难破解,后端可以据此判断是在集成了认证器SDK的应用中发起的。但是也有一些难题,识别信息的生成方法可能会被破解,还有怎么确认是用户发起的还是恶意程序发起的?
2、密钥生成过程中可能被黑客替换,存储和使用再怎么安全也无济于事了。这个在微信的技术资料中提到过,Android的密钥生成有被拦截的可能,不确定当前是不是解决了。这也说明底层框架和操作系统也可能是不可信的,在某些场景下必须慎重考虑。
3、以上两个问题在Root或者越狱之后的手机中更严重,APP、SDK和操作系统都无法信任了,所以很多金融类APP不支持在Root或者越狱的手机上使用指纹认证,不过道高一尺魔高一丈,还是有一些方法来欺骗APP,这也不乏部分用户的支持(自作X啊)。
这个问题有好的办法解决吗?有,设备出厂前就把私钥保存到TEE中。
Android中的密钥安全大家应该知道Android系统是开源的,很多手机厂商都在生产Android手机,市面上有多个厂商在竞争,谁也不服谁,所以要想推广上文提到的出厂前内置私钥的方法,就必须统一标准。在国内腾讯和阿里具备这样的影响力,腾讯搞了SOTER,阿里搞了IFAA,两者都要求手机厂商在产线上生成一对非对称密钥,私钥写入手机TEE,即使拿到了手机当前也没有破解之法,私钥也就不会被泄漏,除非手机厂商搞事情,不过如果手机厂商真的这样做了,就离倒闭不远了;公钥上传到认证服务器,认证的时候用于验证手机APP上传的数据签名,验证通过了就能代表是在对应的手机发起的认证。
同时为了推广这个技术,这种协议还支持别的厂商APP接入进来。但是这样就很容易泄漏APP的商业隐私 ,比如SOTER每次支付都要去腾讯的认证服务器认证一下,据此就可以推断你的业务行为和交易量,所以SOTER又搞了应用密钥和业务密钥,来尽量消除这个商业风险;同时针对Android密钥生成可能被拦截的问题,让手机厂商装个补丁包就解决了,比如替换掉不安全的中间环节。下面来看下应用密钥和业务密钥的产生过程。
应用密钥产生流程:应用密钥在应用首次安装的时候生成,应用密钥的私钥保存在手机端,并使用出厂前内置的私钥签名,然后发到腾讯的认证服务器验证签名,此时应用密钥的公钥会保存到应用的后台。
业务密钥产生流程:在使用登录或者支付的指纹认证注册的时候,应用会再生成一个业务密钥,业务密钥的私钥还是保存在手机端,业务密钥使用手机端的应用密钥进行签名,验证也只需要在应用的后台验证就可以了,此时和腾讯的认证服务器就没有关系了。
这样腾讯就不知道你的实际业务运营情况了,比如每天在线支付多少笔,但是APP安装量还是免不了会暴漏出来,话说APP都要上应用市场的,这个信息其实早就公开了。
关于SOTER详细介绍,可以看官方文档:https://github.com/Tencent/soter/wiki
IFAA的应用过程和SOTER差不多,这里就不再赘述了。另外国外还有一个FIDO联盟,也是解决这个问题的,国内是联想集团的子公司国民认证在推广这个,技术原理也都差不多。
iOS中的密钥安全iPhone的操作系统和硬件都是自己控制的,所以对于安全控制它可以做的很好。
对于本机指纹认证,苹果也提供了Touch ID的API,可以在前端调用指纹认证,但是如果要发送到服务端去验证,基于各种安全考虑,就还是需要一个客户端密钥,这个客户端密钥有没有安全的产生方式呢?我没有找到官方的文档说明,很多基于这个方案的第三方应用可能都是自己生成的吧,尽量做到安全。当然这个也是猜测。
但是微信或者支付宝这种应用怎么能忍呢?SOTER曾经说要支持iOS,最后也是不了了之;IFAA宣传的是兼容支持iPhone 5s 以上所有 iOS 手机,不过它不开源。可能苹果最终还是不想把这块放开,同时基于苹果的强势地位,最有可能是苹果专门给这种应用开放了特定的API,不许外传。
如果是做指纹登录,其实可以直接使用苹果开放的Apple ID登录协议,支持指纹和刷脸认证,会给应用返回认证Token和授权码,应用后台拿着这两个再去找苹果验证。从这个逻辑上看,苹果的后台必然能安全的确认发起请求的客户端身份,所以估计和Android的原理差不多,只不过前后端的每次认证都得苹果来验证。
Web中的指纹认证上面提到过一个FIDO联盟,它和W3C搞了一个WebAuthn标准,它的目的是标准化用户对基于 Web 的应用程序和服务的公钥认证的接口,说人话就是定了一个Web程序中使用公钥认证的标准,所谓的公钥认证就是上文提到的客户端密钥认证技术。这个国内产品好像使用的不多见,不过这件事挺牛的。它可以在Windows、Linux、Mac OS、Android、iOS、智能手表等各种设备中使用指纹识别、面部识别、虹膜识别、声音识别、实体密钥(USB连接、蓝牙连接、NFC连接)等多种方式进行认证,尽可能的摆脱对密码的依赖。
这个技术标准和APP中的公钥认证技术是一脉相承的,主要区别在于APP换成了浏览器,认证模块除了操作系统本身支持,还增加了对专用硬件的支持。有兴趣的可以去了解下。
以上就是本文的主要内容,因能力有限,可能存在部分错漏,欢迎指正。
,