微信指纹支付从设备出厂到完成支付大致可以分成4个步骤、3对公私钥:
1.设备出厂公私钥及tee适配
手机厂商在手机tee的RPMB区域内置私钥A_priv及微信支付的特定ta和SoterKeyStore,然后厂商统一将该设备信息和设备公钥A_pub存储在腾讯服务器(校验设备签名时需要向腾讯服务器发起请求)。
2.生成应用公私钥
某app想在mobile上使用微信支付,则使用soter API向tee发出请求,tee中生成应用公私钥,私钥B_priv存储在tee中,公钥通过A_priv签名后发送给应用服务器,应用服务器向腾讯服务器发出请求校验签名,通过则存储B_pub。
3.生成业务公私钥
对于同一个设备的同一个应用可能存在多个用户(不同账号在同一设备登入),这时需要对每个用户生成独立的业务公私钥C,和第二个阶段类似,在tee中生成业务公私钥,C_priv仍然存在设备中,C_pub通过B_priv签名之后传给应用服务器。
4.使用微信指纹支付
客户端向服务器请求挑战因子challenge(实际为随机数,用于防止重放攻击),客户端在指纹识别通过后调用回调函数onAuthenticationSucceeded,然后在回调函数中将 challenge发送给tee中特定的ta进行签名(微信使用自定义的SoterKeyStore),签名之后从ta(SoterKeyStore)中返回challenge+fid+tee信息+使用C_priv签名后的签名值,发送回服务器进行校验,服务器使用C_pub验签,同时校验challenge值,都通过则表示请求合法。
这里要注意几点:
1)challenge值是用于防止重放攻击。
2)签名是在tee中执行(ta),用户态通过KeyStore向ta发出签名申请。
3)fid相当于每个指纹的hash,理论上每个指纹都不同。
4)tee中指纹认证通过与否都只会回调相关函数并在回调函数中发出签名请求,比如验证通过回调onAuthenticationSucceeded,验证不通过则回调onAuthenticationError,而回调函数在用户态,可能被任意篡改,攻击者可以将onAuthenticationError函数体篡改成onAuthenticationSucceeded函数体,然而由于只有指纹验证通过之后ta才会接受签名请求,所以即使直接篡改也无法欺骗ta签名。
5)指纹验证通过后发送challenge给tee,然后从ta中返回的数据格式如下:
5.微信指纹支付和支付宝指纹支付(ifaa)主要差别
1)手机tee中内置密钥数不同。腾讯soter框架在tee的RPMB中只内置了一个设备私钥;IFAA则需要在设备中内置设备私钥+IFAA根公钥。
2)微信的应用密钥相当于ifaa的服务端密钥,但是微信应用密钥是在设备中生成,而ifaa是直接通过ifaa认证中心给服务端颁发证书。
3)微信由于没有在手机中内置根公钥,所以每次生成应用密钥的时候需要向腾讯服务器发出请求校验签名,而ifaa通过内置根证书+ifaa认证中心颁发服务端证书的方式完成校验。
4)腾讯soter开源,对小商户而言接入方便(无需申请服务端证书);ifaa目前暂时没有开源。
6.总结
总而言之,不论是指纹、人脸、眼纹还是其他特征,生物授权的本质是密钥签名,只有认证通过才签名是生物授权能保证安全的根本原因。