是否可仅通过生物识别无需密码回退检索Secure Enclave中的数据
实现Secure Enclave数据检索绑定生物识别+自定义回退的方案
核心前提
生物识别校验必须和Secure Enclave的密钥访问权限绑定,不能单独做LAContext校验后再读数据,否则会存在被绕开校验直接访问密钥的风险。
步骤1:存储数据时绑定生物识别访问控制
存储阶段就要给Secure Enclave内的密钥加上访问控制规则,从根源限制只有身份验证通过才能读取密钥:
import LocalAuthentication import Security // 创建访问控制规则 let accessControl = SecAccessControlCreateWithFlags( kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, .userPresence, // 若要完全禁用密码回退,替换为.biometryCurrentSet nil )! // 生成Secure Enclave存储的EC密钥对 let attributes: [CFString: Any] = [ kSecClass: kSecClassKey, kSecAttrKeyType: kSecAttrKeyTypeEC, kSecAttrKeySizeInBits: 256, kSecAttrTokenID: kSecAttrTokenIDSecureEnclave, // 明确指定存入Secure Enclave kSecAttrAccessControl: accessControl, kSecAttrIsPermanent: true, kSecAttrLabel: "你的业务密钥唯一标识" ] var error: Unmanaged<CFError>? guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { // 处理密钥生成失败逻辑 return } // 用生成的公钥加密业务数据,密文可存在普通Keychain或沙盒
步骤2:检索数据时实现自定义回退逻辑
通过修改LAContext的配置隐藏系统默认回退按钮,自己接管验证失败的处理逻辑:
let context = LAContext() context.localizedFallbackTitle = "" // 隐藏系统默认的"输入密码"回退入口 var authError: NSError? // 先判断设备是否支持生物识别 guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) else { // 设备不支持生物识别,触发自定义回退逻辑 customFallback() return } // 发起生物识别校验 context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "验证身份以读取数据") { success, error in DispatchQueue.main.async { if success { // 校验通过,读取Secure Enclave内的私钥解密业务数据 decryptBusinessData() } else { // 生物识别失败,触发自定义回退逻辑 customFallback() } } }
关键注意事项
- 如果你需要完全禁止设备密码作为验证方式,创建SecAccessControl时把flag替换为
.biometryCurrentSet,该配置下后续用户新增/删除生物特征,旧密钥会直接失效,也完全无法通过设备密码解锁访问 - Secure Enclave仅支持存储EC类型的加密密钥,无法直接存储任意业务数据,必须通过「密钥加密业务数据、密文本地存储、验证通过后用密钥解密密文」的流程实现
- 密钥的访问控制属性绑定在Secure Enclave的硬件层面,即便应用被破解也无法绕开校验读取密钥
内容的提问来源于stack exchange,提问作者Paul Ancajima
相关产品推荐
相关产品推荐

