大多数浏览器和
Developer App 均支持流媒体播放。
-
使用 App Attest 和 DeviceCheck 减少欺诈
了解如何使用 Apple 强大的反欺诈工具 App Attest 和 DeviceCheck 来保护您的 app 和内容。深入探究如何将其与您的 app 集成来部署 App Attest,从而阻止您的 app 和内容在未经授权的情况下遭到修改。此外,我们还将展示如何使用 DeviceCheck 来确保您能够区分客户,辨别哪些已在您的 app 中收到优惠内容,而哪些是通过非法手段取得优惠内容。
资源
- Accessing and modifying per-device data
- Assessing fraud risk
- Establishing your app’s integrity
- Validating apps that connect to your server
相关视频
WWDC21
-
下载
♪ ♪ 大家好 欢迎收看本期视频 “使用App Attest 和DeviceCheck减少欺诈” 我是严学瑞 在App Store信任 与安全团队工作 很高兴可以和大家讨论 使用App Attest 和DeviceCheck 保护你的应用程序 在Apple公司 我们一直致力于 确保App Store 对用户和开发者而言 是安全可靠的 在本期视频中 我们将讨论 工程细节内容 如想了解相关业务和概念详情 可参考视频“保护你的账户 推广活动和内容” 来自2021年的WWDC会议
在iOS 11中 我们引入了DeviceCheck框架 DeviceCheck框架有助于减少 对促销优惠的欺诈行为 假设你的应用程序 新增了某项功能 为了推广该功能 你提供一项免费 只可使用一次的促销优惠 也许会有人多次领取该优惠 通过一遍又一遍地重装应用程序 以获得免费的优惠 很有可能 你想限制优惠的领取 如每个设备只可领取一次 而不是允许应用程序 被重复地安装 导致优惠的再次领取
现在 DeviceCheck 可以帮助你检测 一个设备是否 已经领取过促销优惠 或者一个设备 是否存在欺诈行为
它允许你在Apple服务器上 持续存储单个设备的 两个二进制位信息和一个时间戳
这两个二进制位对你的应用程序 有何意义 由你来定
其状态由Apple负责维护 可供你进行更新和查询
同一个开发者的所有应用程序 共享这两个二进制位 因此需牢记这两个二进制位的定义 以便其适用于你的所有应用程序
它们的状态会维持不变 不论是应用程序重装 不同用户登录同一设备 甚至是“抹掉所有内容和设置” 考虑使用时间戳 重置这两个二进制位 在做选择的时间节点 基于你的促销和业务策略
想了解更多 关于DeviceCheck的内容 可参考视频 “隐私和你的应用程序” 来自2017年WWDC大会 以及DeviceCheck框架文档
以上介绍的是DeviceCheck 接下来 我将介绍App Attest 它同样在DeviceCheck框架之中
当你的服务器接收到一个请求时 可能会很难判断 该请求确实来自你的应用程序
App Attest允许你的应用程序 附加一个基于硬件的断言 作为访问请求的一部分 你的服务器可使用断言 核实访问请求是否来自 正版应用和正品Apple设备 设想一下 你设计了 一款很棒的应用程序 旨在鼓励用户通过旅行 发现收藏品 结果却发现 被篡改的应用程序 允许收集所有藏品 连家门都不需要出
或者想象下 在多玩家竞技比赛中 当玩家看到其他对手 通过作弊手段 获得了无限加成 从而在排行榜上快速蹿升 他们的那种沮丧之情
或者再想象下 你在一个周六醒来 满心欢喜地发现 服务器端有大量的访问请求 然而经过调查 你发现这些访问请求 根本不是来自你的应用程序
App Attest可以协助你 识别应用程序的 正版和篡改版本 进而保护应用程序的 用户体验和你的业务
App Attest提供三个关键性能 有助于保护你和你的用户
App Attest允许你的服务器 核实一个请求 是否来自应用程序的合法版本 通过满足三个条件: 请求来自正品Apple设备 运行你的正版应用软件 且有效负载未遭篡改
让我们详细介绍App Attest 提供的这三个性能 App Attest的核心 在于一个安全密钥对 以及一项由Apple签名的认证 证明密钥对来自 正品Apple设备 使用App Attest API 通过Secure Enclave模块 存储和访问私有密钥
应用程序可以使用密钥 对服务器请求进行签名 服务器可以通过核实签名 验证请求是否来自 正品Apple设备
对于在Apple设备上 运行的应用程序 它必须经过签名 任何人如果篡改你的应用程序 必须使用他们的身份重新签名 这就不可避免地修改了 应用程序的身份
认证中包含应用程序身份 的哈希版本
通过比较你的应用程序身份 和认证中的身份 就可以判定 一个访问请求 是否来自篡改应用程序版本
由于你已经知道请求来自 正品设备和正版应用程序 让我们来讨论下请求有效负载
在向你的服务器 发送一个有效负载之前 可以通过使用经验证的密钥 利用App Attest 对有效负载的摘要进行签名 这会生成一个有效负载的断言
你的应用程序会将有效负载 和相应的断言 传输至你的服务器 通过验证有效负载的断言 你可以确认有效负载 没有在传输中被篡改
以上就是三大关键性能 现在让我们来稍微 谈谈隐私的话题
在Apple 我们高度重视隐私问题 我们坚信隐私是 一个健康应用生态系统的基石 App Attest的每个要素 都将隐私问题考虑其中
认证的设计可用于验证 正品设备 同时防止被追踪 认证是匿名的 且不包含硬件标识
应用程序的每次安装 App Attest密钥都是唯一的 这意味着一个App Attest密钥 无法继续存在于 应用程序的重装 也无法备份 以及无法在跨设备中同步 你在设计应用程序时 请记住这一点
既然你现在已经 了解App Attest的价值所在 让我们更深入地讨论 如何将其引入你的应用程序中 将App Attest引入你的应用程序 包含三个基本部分 创建App Attest密钥 证明和验证这个密钥 生成和验证断言 让我们以创建App Attest密钥 作为讨论的开始 所有App Attest的调用 都受到isSupported函数的检验 支持App Attest的设备 需要包含Secure Enclave 但也有一些情况 比如应用程序扩展 函数isSupported的返回值 仍然为false 你的应用程序必须合理地 处理这些情况
应该将故障作为一种风险信号 而不是直接拦截访问 首先 将一个访问归类为不可信 然后 根据你的风险评估逻辑 评估是否允许该客户端 使用敏感功能
另一种方法是监测 那些访问你的服务器时 声称不支持App Attest 的设备突增 如果支持App Attest的设备 比例骤减 这也许预示着 篡改版本应用正试图绕开检查 在一个App Attest密钥 顺利生成的情况下 让我们接着验证这个密钥 为防范中间人攻击和重放攻击 我们需要来个单次的服务器请求 让你的服务器将请求传至应用程序
将认证与用户的账户身份 或其它参数相连 散列这些参数 和该请求 以创建clientDataHash 使用上一步骤 的clientDataHash参数 以及密钥标识 我们就可以 开始调用attestKey API
attestKey将使用私有密钥 为设备创建一个硬件认证请求 然后将请求 发送至Apple 进行验证 一旦通过验证 Apple将 一个匿名的认证对象 返回至你的应用程序 将认证和相关的自定义有效负载 发送至你的服务器进行验证 好的 既然你的应用程序 已经发送认证至 你的服务器 让我们试着对其进行验证
该认证遵循网络身份验证标准 其包含三部分内容: 一系列由Apple签字的证书 认证数据结构和风险指标回执
让我们关注 你需要验证的重要部分
证书部分包含叶证书 和中间证书 App Attest根证书 可以在Apple的 私有公钥基础设施库中获得 通过验证整个证书链 可以确定一个设备是否为 正品Apple设备
当你调用attestKey时 一个一次性使用的哈希值 也被称为一个随机数 即从clientDataHash 和其它数据中被创建 该随机数包含在叶证书之中
为防范篡改 你在服务器中 重现该随机数 并进行匹配验证
认证器数据模块包含若干项内容 如一份应用程序身份的哈希版本 这用于验证服务器的访问 来自你的应用程序
密钥认证还包含一份回执 你可以存储并在日后用于 向Apple请求一份风险指标数据 我将在视频中介绍更多 关于这部分的内容
如果一切都验证成功 App Attest密钥是对的 存储密钥和客户数据 以备验证后续请求之用
不是所有验证失败 都源于认证无效 合理地处理其它相关情况 比如isSupported函数返回值为false 因为访问量增加时被节流 或者普通网络故障 这样你就可以将验证失败 作为你的整体风险评估的信号
想了解更多关于 实现验证的详细内容 请参考相关文档 调用attest-Key API 会生成你的应用程序 和App Attest服务之间 的网络访问 每个应用程序每次只发生一次 然而 如果应用程序的用户基数大 大量用户的应用程序可能会共同 向App Attest发送很多请求 为了管理好资源 避免被限流 需要确保你已经解决了 安装量的问题 举个例子 如果你有一百万日活跃用户 你可能需要一两天来提升效能 如果你有十亿日活跃用户 这很棒 你可能需要不止一个月
由于有了认证密钥 你可以 调用generateAssertion API 来保护你的应用程序和服务器 之间的敏感通信
断言流比断言更简单 因为这里已不再 涉及Apple服务器
所有断言使用的密钥 产生于设备端 并在你的服务器上进行验证
首先从服务器 发起一个独特的请求 然后生成有效负载的摘要 和调用generateAssertion generateAssertion 将使用有效负载摘要 一个随机数 并使用App Attest 密钥对其进行签名
随后 你的应用程序 可以将有效负载 和断言 发送至你的服务器 最后 你的服务器 会验证该有效负载
断言有效负载由 这样的高级结构组成 签名和认证器数据
为了验证签名 在你的服务器上 反向操作 重现随机数 然后使用公钥验证签名
如果签名有效 你就可以确信 有效负载没有被篡改
认证器数据部分 包含应用程序身份哈希值
验证该列表 可以确认断言 来自你的正版应用程序
认证器数据也包含 一个不断增长的计数器 为防范重放攻击 可在你的服务器上保存计数器的值 并指定这个值随着 每个后续请求 而增加
有了密钥 你现在可以按需 不断重复该过程 由于生成断言 不需要访问Apple服务器 它是个加密操作 会带来一定的时延 当你在应用程序中 加入App Attest时 在设计时需要将这一点考虑在内
断言非常适合 重要但频率不高的访问 这些访问可以应对 额外的延迟和必要的计算
对于高频实时的网络指令 断言可能不太适用
值得祝贺的是 你现在已经 完成了App Attest的实施 单是完成这一点 你就可以开始 将接收到的服务器访问 分类为正版或篡改版本 并将这个重要的欺诈信号 运用于你的业务逻辑 但问题没这么简单 攻击者可能会试图 绕开App Attest 通过使用一个设备 创建很多个App Attest密钥 然后使用那个设备 充当许多篡改版本应用程序 与你的服务器之间的通信媒介 为检测这样的行为 我们提供一项服务 名为App Attest风险度量服务 它规定一个设备能为 你的应用程序 创建的大致密钥数量 重新调用attestKey将返回 认证和一份风险指标回执 你的服务器可以将该回执 发送至风险度量服务 然后兑换一份新的回执 这份新的回执将包含风险指标
定期地 你可以兑换最新的回执 以获得应用程序及对应设备 最新的指标
这是回执结构的高级视图 它是个加密消息的语法标准容器 详情可参考DeviceCheck 框架文档里的 “评估欺诈风险”内容
轻App 是iOS中令人兴奋的功能 我们在iOS 15中 为轻App 增加了对App Attest的支持 为支持轻量版应用 无缝升级至完整版应用 在App Attest环境中 轻量版和完整版应用程序 拥有相同的应用程序身份 在你的服务器端 验证应用程序身份时 请务必记住这一点
当轻App被手动删除 或者服务终止时 他们的密钥将会失效 正如完整版应用程序 未被安装一样
好的 关于轻App就介绍这么多 现在要记住成功运用App Attest 的关键要素 在服务器端验证 而非设备端 应用程序也许会被篡改 进而使验证码失效
将一次性的服务器请求 加入到你的断言流中 以阻止网络重放攻击
处理失效场景 比如isSupported函数 返回值为false 访问量增加时被节流 或者普通网络故障 将故障作为风险评估的信号
App Attest and DeviceCheck 提供的信息 可供你应用于整体欺诈评估 使用DeviceCheck减少 促销优惠的欺诈行为
利用App Attest检测 应用程序的篡改版本 保护你的内容和用户体验 感谢收看 我期待看到你的应用程序 得到App Attest 和DeviceCheck的保护 再见
-
-
8:02 - Create an App Attest key
let appAttestService = DCAppAttestService.shared if appAttestService.isSupported { appAttestService.generateKey { keyId, error in guard error == nil else { /* Handle the error. */ } // Cache keyId for subsequent operations. } } else { // Handle fallback as untrusted device }
-
9:34 - Generate key attestation
appAttestService.attestKey(keyId, clientDataHash: clientDataHash) { attestationObject, error in guard error == nil else { /* Handle error. */ } // Send the attestation object to your server for verification. }
-
13:14 - Generate assertion
appAttestService.generateAssertion(keyId, clientDataHash: clientDataHash) { assertionObject, error in guard error == nil else { /* Handle error. */ } // Send assertion object with your data to your server for verification }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。