大多数浏览器和
Developer App 均支持流媒体播放。
-
加密技术与您的 App
系统框架会以透明的方式加密静态数据和传输中的数据。只需设置一项属性,便可利用这项功能。不过,您或许希望采取额外的措施来保护您的用户数据。CryptoKit 是一种新的 Swift 框架,可让加密操作变得前所未有的简单、安全,不论您只是需要计算哈希值,还是要实施更为高级的身份验证协议,都可以使用该框架。
资源
相关视频
WWDC19
-
下载
下午好 各位下午好
欢迎来到比特币专场 开个玩笑 欢迎大家来到 Cryptography and Your Apps 专场 今天 我的同事 Frederic 会和我一起向你们展示 在 Apple 产品上使用密码 变得前所未有的简单 我是 Yannick Sierra 我在 Apple 负责管理 加密工程团队 那么今天一方面 我们会带来一套系统功能 来解决一组常见安全问题 另一方面 我们还将 为大家带来一个全新的 为加密操作服务的 Swift API 我们很高兴能为大家讲这些 你们来到这里 一定是因为想要 保护一些信息 对吧
我们知道各位 作为开发者和用户 都认为保护用户的信息 是十分重要的
我们有各种各样的信息 它们都十分敏感 包括个人资料信息 比如电话号码 和电子邮件地址 你的 App 可能也会 处理一些用户信息 如照片或音乐 通过 App 来处理和加工
你的 App 也会 处理商业素材
这可能是你的 App 提供给用户的付费内容 或者是如手机银行 这样的场景中的账户信息
所有这些信息 我们都务必保护其安全 那么你就需要使用很好的工具 在 Apple 里 安全和隐私 是核心价值 它根植在我们所开发的 所有功能之中
加密技术是其中一个重要的部分 举个例子 对于设备完整性 我们使用加密技术 来验证在平台上运行的 软件的完整性 以确保它不被破坏 同时保证其安全属性 没有被篡改
我们用加密技术来保护静态数据
我们在众多用户 喜爱的 App 中使用加密技术 用户广泛地使用它们 来捕捉和分享非常私人的时刻 这是一个在信息 Safari 浏览器和 iCloud 的例子
我们有超过十亿的设备 因此我们大范围地使用加密技术
那么你可以想象 风险也是非常高的 性能对提高用户体验来说 是至关重要的 电量是保证我们 全天使用的基础 而安全则是基石
现在 我们来进一步了解一下 加密技术
加密技术其实是一个工具 它为一系列基本属性 提供解决方案
比如身份认证 它能够 让你知道是谁向你发送了信息
加密 就意味着 只有你才能解密该消息 而完整性 则代表着 没有人可以在你之前 修改该消息的内容 为解决更广泛的 安全问题 我们将加密功能 结合到加密协议中 这并不容易
事实上 你们中的很多人 大多数人可能都听过这个说法 不要使用加密 对吧 这个说法有很好的理由 有很多地方都可能出错
比如它有可能选中 错误的原语 从而使你得不到 你想要获得的安全 或者它也可能添加了正确的 原语 但没有正确使用它们 而最低级的错误 即安装启动的时候 就可能泄露了隐私或密钥 这可能会造成定时攻击 或 Padding Oracle 攻击
这就是为什么 加密十分困难 新闻上我们可以看到 无数关于加密协议 失败的例子 而最糟糕的是 安全漏洞也许不是当时 就能发现的 也许要等到几年后 有人报告说发现了一个漏洞
这就是风险高的原因 所以要保证其正确性需要 花费很多努力
设计一个强大的协议 需要花费大量时间和技巧 还需要你作为一个加密专家的专业知识
甚至当你设计出协议的时候 工作仍没有结束 你还要做大量连续的工作 来监控新的攻击 看看什么适用于你的代码 然后响应它 但有时并不是那么简单 它们可能是彼此依赖的 那些你选择整合进 你的 App 中的库文件 在一些情况下 你也需要修改并传输协议 同时管理所有的 可解释的场景 所有这些是个大工程 它会花费大量的时间和精力 让你无暇实践可能有的精彩想法 或者下一个很酷的功能
这就是为什么你可以 真正从原生功能中获益
我们的理念一直是 为一系列常见的问题 提供完整的解决方案 而你无需为此费心
对你来说 它增加了风险 和工作量 我们完全可以 通过我们平台上的 代理的硬件功能 来实现更好的安全性
现在 我们来看一组 你们可能非常熟悉的 很常见的场景 我会先开始讲如何 保护一个设备上的数据 接着我们可以看看 保护凭证和密钥 之后是跨设备和用户的数据共享
接着是保护网络链接安全 那么最后是 用证书验证间接联系人
现在 我们来看第一个例子 相信你们中的很多人 已经发现了该场景 并且在努力保护设备上的数据 那么 我建议你们不要 仅仅是复制粘贴你在 一些网站上发现的东西 最好使用数据保护
数据保护综合了 密码的长处 和 Secure Enclave 中的 硬件技术 来确保密钥的安全性 同时使加密数据不能被 暴力破解密码 但还有更多优点 数据保护提供了 破解后的复原
破解后复原 也称前向保密性 它能确保如果攻击者 攻击了设备的密钥 之后用户更改了密码 那么旧的密码 都不能被用来恢复 所有之后加密的数据
这一点可以说至关重要 如果你想要了解更多 数据保护能做的事情 你可以看看 iOS 安全白皮书 来获得更多信息 有一件事你需要知道 就是当你的 App 出现问题时 你可以设置 不同的保护属性 首次身份验证后就可以设置 而数据甚至一直会被保护
直到用户在开机后第一次 将手机解锁
这很不错
今天 你可以做得更好 我们有完整的文件保护 完整的文件保护 意味着 只有在用户解锁他的手机后 数据才能获取 只要用户锁起他的手机 将其放入一个口袋或包里 数据就再一次被保护起来了 这样使用起来真的很方便 这里有一个例子 你唯一需要使用的 就是这个选项 completeFileProtection 不能比这更简单了 对 如果你现在还没使用这个选项 请回去查看你的 App 看看你可以在哪里使用它 以获得最佳级别的安全性
现在 除了文件 你想要保护的 也许还有更为敏感的信息
也有身份验证令牌 这样的证书 它们用于对服务 或加密密钥进行身份验证 但不要将它们 编写成默认值 像我们可以 在所有平台上看到的那样 相反 我们有钥匙串
SecItem API 中的钥匙串 让你能像在本地钥匙串中一样 写那些项目 这意味着 它们会继续保留在该设备上 或者在 iCloud 钥匙串上 在那里 他们将所有的设备同步 从而实现一种
这需要用户账户能够 进行双重验证 而对于钥匙串 你会发现 它对我前面提到的文件 和一些额外文件 有非常相似的保护 这里 我要再推荐你 可以去看看那个文档 来进一步学习
除了了解何时可用密钥外 有时知道用户 如何及何时 对其进行身份验证 也很重要
所以在这里 我们用 LocalAuthentication
LocalAuthentication 使你可以 根据何时可以执行一个操作 来进行限制 例如 你可以定义 用户需要使用 Face ID 这样的生物鉴定识别 进行身份验证 这样做非常方便 同时在这方面 在 macOS 上 我们有一些更有意思的操作 在 macOS 上 你习惯了 设备身份验证属性 它为用户提供了两种方法 来进行身份验证 分别是 密码和支持 Touch ID 进行验证的 Mac 上的生物鉴定识别 今年 我们非常高兴地宣布 现在 你不需要在 App 上做任何的改变 用户就可以用 Apple Watch 来进行身份验证 只要双击 Apple Watch 这是个很棒的全新体验 它将会减少密码的使用 减少摩擦 从而提高用户体验 现在 因为有了这些新功能 我们增加了两个新的规则 第一个是将身份验证 简化为只用生物鉴定识别 和 Watch 第二个则是只用 Watch 验证
我们期待看到 你将如何在你的 macOS 上的 App 中使用这些
那么 我之前提到过钥匙串 这里有一种简单的方法 可以将一个账户 在所有设备上的项目同步 那么如果你有数据怎么办呢
好 对于数据我们也有很好的 解决方法
CloudKit 它使你可以 在私人 CloudKit 数据库里 对素材进行加密 相应的数据就会 在所有的设备间共享 而用户不需要登录 App 这很不错 甚至你可以用它 来共享给所有的用户
它的工作方式是 Apple 将作为一个信任方 来帮助管理 iCloud 身份 和对数据的控制 这里我再举一个例子 这个设置起来很容易
从文件中 我们创建一个素材
用这个素材 我们创建了一个记录 然后我们将这个记录 上传到私人 CloudKit 数据库 这样就可以了 如果你想 向其他用户添加共享 API 也是可以做到的 如果你之前没有关注过 CloudKit 那么这是一个很好的时机 你可以去查看说明文档 看看它对你来说 有多么强大 那么 我们之前说了 保护设备里的数据 然后将其在设备间共享 甚至是共享到另一用户的设备 比如 在你想对来自你自己的 服务器的数据执行此操作的时候
你想在哪里建立 一个安全连接
安全连接 真的十分重要 因为它能帮助我们 保证用户在使用你的 App 时的所有信息的 保密性 同时保证 该信息的可信度 确保它不被篡改
那么在这里 你首先不应该做的就是 只是尝试使用你的自定协议 有一个很好的解决方案 这是一个标准的解决方案
传输层安全协议 它在我们的平台上真的很好用 因为我们有两个很棒的 API 第一个是网络框架 你可能已经在 去年的 WWDC 中发现了这个 第二个就是 URL 会话 你可能知道它是 App 传输层安全的一部分
而在 URL 会话中 我们只需要使用一个 https TPS 端点 在这两种情况中 我们依赖的都是 包含很多默认值的 TLS 默认值保证密码套件提供 强大的安全性 包括完美前向保密 以及 Apple 产品上 最有效的算法 或者在默认情况下
实现 TLS 也要使用 TLS 1.3 你可能不是很熟悉 TLS 1.3 它相对于之前的版本 有很大的改进 它可以大大提高 安全性和效率 通过减少一些运行行程
如果你还没有使用 TLS 1.3 那么请你试着将其 应用在你的服务器上 而你不需要在你的 App 上 做任何改变 就可以受益
好 为了向你展示它真的很简单 我这里有两个使用网络框架 和 URL 会话的例子 但在讲这两个例子前 我想要强调的是 安全传输这种方法 我们不再推荐 我们希望你 转用网络框架 和 URL 会话 如果你正在使用安全传输的话 我们为此准备了很多的例子 首先是网络框架 当你建立了一个连接 你需要做的唯一的事就是 加上 using:tls 好了 你添加了该 TLS 连接 会带给你更好的安全性和性能
然后是 URL 会话 在这里 你只需要用 http 端点 好了 在一些情况下 你也许无法用 TLS 例如 如果你已经在尝试 通过一个内容发布网络 来保护数据 这时 你管理那些证书 而对于证书来说 首先要避免的就是 将它用在解析器上 或尝试用一个你在网站上 随意发现的解析器 解析器非常脆弱 因为它包含大量的攻击暴露
这是很严重的问题
在平台上我们有 SecTrust SecTrust 提供了一个简单的方法 即根据一个信任规则 来验证证书 而信任规则可能包含 过期信息 作废信息 而直到证书已经被验证了 你才知道你可以使用密码 注意 如果你使用 TLS 的话 你就不需要担心证书的问题了 一切都在为你安排好了 好 在这个版本中 我们很高兴介绍一个 SecTrust 中的新函数 该函数综合了 你之前能做的两件事 一方面 这是一个函数 它允许异步执行 通过显式操作 来完成一个验证证书 这样你的 App 就可以 在证书被验证的同时 进行其他的事 但同时 这个函数 可以进行更丰富的处理 那么 作为一个开发人员 你知道万一失败了要怎么办 你可以进行调试 但同时 你可以在你的 App 里 建立逻辑来对不同的 错误场景作出回应 那么这个新函数将会 让调试变得更为 方便和简单 我们期待着你能运用它 那么 我刚刚向大家介绍了 五种不同的场景 对于这些场景 我们有非常易于使用的解决方案 它们提供了很好的安全性 你只需要使用默认设置 或者修改几个属性就可以 在这里 我们又一次地 受益于与硬件的深度融合 以此提供安全特性 否则我们是很难 提供这些特性的 那么 无论在哪个场景中 当你遇到它们 就去使用系统框架 如果你已经这么做了 就要保证你正在使用的 都是最好的属性 这样你才能 以尽可能好的方式 来保护用户和商业素材 我们明白在一些情况下 使用系统功能 也许对你来说并不是那么实用 例如 你可能需要 在适用系统之外具备互操作性 你可以用你的服务 来进行身份验证 或者只是给一个 需要实现的规范 对所有这些例子 我们现在 要介绍一个很棒的解决方案
Apple CryptoKit Apple CryptoKit 是 新的 Swift 加密 API 其设计理念与我们 所讨论的功能的设计理念相同 它让你能够很容易地 访问加密函数 也很难误用函数 我们很高兴在本次发布中介绍它
现在 我要交给 Frederic 他将向你们介绍 这个全新的 API 下面有请 Frederic 上台 谢谢 Yannick 大家好 我的名字是 Frederic Jacobs 我来自 Apple 的 加密工程团队 很高兴能向你们进一步介绍 Apple CryptoKit 我们认为你一定会喜欢 在 Swift 中实现加密协议 关于 Apple CryptoKit 有四个方面 我想要在今天下午 与你分享 首先 我们要谈一谈 CryptoKit 和 Swift
第二 我们会向大家介绍 能够在 CryptoKit 里 获得的算法 第三 我们将讨论一下 Secure Enclave 和生物鉴定识别 最后 我们会谈谈性能 我们开始吧
在过去 当你从 Swift 中 调用 C 加密 API 时 你可能不得不编写 这样的代码 你需要分配缓冲区 分析出每一个 缓冲区的尺寸大小 也有像随机数这样的值 你可能需要查找 该值的安全值是多少 然后 你将所有这些 嵌套调用至 你传递指针的加密函数中 同时这里没有参数标签 来帮你弄清 哪个指针需要进入哪个参数 相比之下 用 Apple CryptoKit 你可以只写一行代码 来进行完全一样的操作
是不是很棒呢 那么 为了完成这个 你将你想要加密的数据 进行传输 在这个例子里 我们使用 AES.GCM 同时 我们用你想要加密的 数据的密钥 这就好了
你也许还需要 生成自己的加密密钥 当你从 Swift 中
我们首先需要 转换一些位和字节 因为加密密钥 通常是用位来表示的
接着你需要为 这一数量的字节 分配一个缓冲区 并使用系统随机数生成器 来用加密安全的随机数 填充该缓冲区
接着 如果出现错误 你必须处理它
然后你终于可以使用该密钥了 当使用完该密钥时 即使你忘记把它归零 也可以将其从内存中移除 而使用 CryptoKit 只要一行代码就可生成一个密钥 你调用 SymmetricKey 初始化程序 然后传输 你希望密钥持有的一定量的位
我们能在释放时将该密钥归零 因为只要了解该值的 自动引用计数 无论它什么时候被释放 我们都在将 该缓冲区归零 好 CryptoKit 和 Swift 我们有一个强类型的 API 无论你何时初始化一个值 我们都在验证 你所传递的数据 是否为该参数的一个强值
多亏 Swift 的内存管理模型 我们才能够在释放时 将所有分配在 CryptoKit 里的秘值归零
我们将对一些 如消息身份验证代码之类的值 执行公平的一致性 如果你熟悉该内容的话 你就能够通过 只使用 == 操作符 在恒定的时间内 来对双消息身份验证代码 进行验证
CryptoKit 也定义协议 这样你可以在 哈希函数 H 上编写通用代码 如果在你代码库的多个位置中 需要传递不同的哈希函数 那么你可以只编写一次代码 然后确定函数的参数 来调用一个不同的哈希函数
那么 我们讲过了 CryptoKit 和 Swift 接下来我想深入讲讲 CryptoKit 中所支持的 算法集
所有算法都是标准的 同行评议的算法 我们来看看 CryptoKit 中支持什么
这里支持哈希函数 消息身份验证代码 认证加密 密钥协商 以及签名
这其中的一些算法 是我们之前在 如 Common Crypto 或 SecKey 等框架中 就支持的算法 但有一些算法 则是我们首次支持的算法 我将它们用绿色标出 注意我们还有一个非安全的模块
该模块提供如 MD5 和 SHA1 这样的算法 这样即使你需要使用一些 不再满足最佳安全标准的算法 你也可以使用 CryptoKit
我们通过一些例子 来看 CryptoKit 是如何工作的 让我们从哈希函数开始 哈希函数会生成 确定的固定大小的输出 我们称其为摘要 与 Swift 中 Hashable 希的不同 CryptoKit中的哈希函数 提供了如防碰撞等加密特性 这意味着你很难找到 两个会哈希出相同摘要的输入 计算该哈希十分简单 就像在你想要使用的哈希函数上 调用哈希方法 然后传递所要哈希的数据那样
这里我想要哈希一些音频数据 那么我会用 SHA256 哈希函数 来计算一个摘要
那你也许会从输入流中读取它
在这种情况下 你需要以增量来计算摘要
首先你初始化一个哈希 通过在哈希函数上 调用 MT 初始化程序 接着传送你想要哈希的数据 然后为此一次或多次地 调用 update() 方法 当你想要计算该摘要时 你只要立即在哈希上 调用 finalize() 方法 然后它就会返回摘要 接下来 我们来说说 认证加密 这也是你们一直想知道的 正如它的名字所示 它可以同时提供认证和加密
在加密协议中 缺少认证 会导致很多攻击 将身份验证 和加密手动结合 会导致如 Padding Oracle 这样的攻击 所以 我们非常乐意将它
我正在做的一个项目 这是一个徒步旅行 App 该 App 上的大多数内容是免费的 但也有额外的内容 你可以在 App 里花钱购买 一旦购买了该内容 你就可以获取额外的内容
我正在使用一个内容发布网络 以此来保证随着用户群的增长 下载的速度仍然很快
为了获得该内容 我首先检查了我的服务器 看 App 内购买是否有效 接着从服务器中获取到密钥 然后通过手机传递过来
我从内容发布网络上 下载该加密数据 然后使用密钥 来将加密内容解密 如果密钥正确 且在内容发布网络上的内容 没有被篡改 那么我就可以获取地图数据 下面我们来看如何转化为代码 我们首先用服务器 获取的密钥数据 初始化一个 SymmetricKey 然后我们初始化一个密封箱
在这个例子中 密封箱里有什么真的不重要 但是要知道如果你 正在实现一个规范 该规范要求你以一种特定的方式 将随机数 密码文本 和标签结合起来 那么你就可以使用密封箱来完成 如果你要实现 一个需要你传输 特定随机数值的协议 我们也能支持这个操作 但是在这个例子里 我们要看看简单的情况
好 我们将下载的数据 作为一个 combined 传输到密封箱里 既然我们有一个密封箱 我们就可以打开它 通过在密码上调用 open() 方法 然后我们传输密钥 就是这么简单
接下来 我们说一说签名
签名被用来 使用一个私钥 对数据进行身份验证 使用签名我们可以 用关联的公共密钥来验证数据 我们来看一个例子 这里我们想要用签名 来授权操作 而这里的操作可以是一个 双重验证登录 或一些敏感交易事项 比如给 App 中的其他用户汇款
为此 我们首先要 在设备上生成一个私钥
接着获取相关联的公共密钥 关联的公共密钥 是用你的服务进行注册的 一旦我们想要执行该操作 我们就用私钥 生成交易数据上的签名 然后将该交易数据 和签名发送给服务器
服务器会验证 该签名是否正确 如果签名正确 它将开始执行操作 下面我们看看这组代码 为了生成一个 强加密的私钥 我们调用 PrivateKey 初始化程序
然后我们想在服务器上 注册一些公共密钥数据 首先我们要获取公共密钥 通过私钥上 调用公共密钥 然后我们要说 我们想从公共密钥上 得到的表示形式 公共密钥有多种表示形式 而在 CryptoKit 中 我们支持许多公共密钥
这种情况下 我们使用紧凑表示 与往常一样 我们将私钥 存储在密钥链中
为了实现这一点 开发者门户上提供了 示例代码 要生成签名 我们要在私钥上 调用 signature() 方法 然后传输我们 想要签名的交易数据 我们就可以返回签名
现在 保护这些操作的密钥 是十分有价值的 所以我们想要给它 最好的安全保障 这时候就轮到 Secure Enclave 了
Secure Enclave 是 基于硬件的密钥管理器 它与主处理器隔离 来提供额外的安全层 它被用作关键系统特性的一部分 如 Touch ID 或 Face ID
让我们看看如何改进 使用签名来利用 Secure Enclave 的代码 我们首先检查 Secure Enclave 是否可以在设备上获得 我们通过在 SecureEnclave 上调用 isAvailable 来完成这一步 从这里开始 我们可以使用 和之前生成时完全一样的代码
来生成密钥 同时在 Secure Enclave 里 生成签名 注意 为了完成这一步 我们只需给 调用的 PrivateKey 初始化程序 添加前缀 SecureEnclave.
用 Secure Enclave 就是如此简单
使用 Secure Enclave 的一个优势是 你可以限制密钥的使用 在本例中 我们想说 我们在 Secure Enclave 上 生成的密钥 只有在设备解锁时 才能访问 且该密钥只在该设备上可用
我们可以进一步限制密钥的使用 方法是当我们使用 私钥执行操作时 我们要求用户在场
要求用户在场意味着 用户要么按提示进行 生物鉴定识别 要么按要求 输入设备密码 既然我们已经组成了一个 访问控制规则 我们只需将其传递给 正在生成的密钥的初始化程序 就可以执行该策略
你可能希望为用户 提供一些额外的上下文 来说明为什么需要他们 进行身份验证 那么 我们可以传输一个 LocalAuthentication 上下文 在本例中 我们想要 LocalAuthentication 上下文的 00:35:58.166 --> 00:36:00.376 A:middle 有效期为十秒
因此用户在这段时间内 将不需要 进行身份认证 我们想告诉用户 他们需要进行身份认证 因为他们正在允许 给 Bob 转账十美元 要使用这个认证上下文 你只需要将它 传给密钥的初始化器
CryptoKit 建立在 corecrypto 顶端 corecrypto 是 Apple 的 本地加密库 它支持之前 Yannick 描述过的 所有系统框架 在为你带来 Accelerate 框架的团队 及 CPU 设计团队的帮助下 corecrypto 手工调整了汇编代码 将每个周期 从每个支持微架构中压出
除此之外 因为它使用了 corecrypto 所以它利用了 corecrypto 中的 安全缓解措施 比如侧通道阻抗 而且 corecrypto 经过了 FIPS 验证 这意味着你可以用 符合 FIPS 的方式使用 CryptoKit Yannick 用这张幻灯片开始 为大家展示了很多漏洞的类别 它们会出现在 加密协议和加密实现中
有了 CryptoKit 我们开始 消除这些漏洞类别中的一些 但 CryptoKit 仍然是一个 底层加密 API 虽然它非常强大 可以实现各种各样的协议 甚至是损坏的协议 但并不是所有的加密缺点 都可以在密码库级别上 得到解决 因此 我们强烈建议你 如果可以的话 要依靠一个更高级别的系统框架 这仅仅是个开始 我们想要继续帮助你 发布尽可能安全的 App 通过提供 API 来帮助你 防止你 App 中 安全的法律漏洞 我们非常期待看到 你在你的 App 中使用 CryptoKit 在本次会议的网页上 你会找到一个 CryptoKit 说明文档的链接 可以在 Xcode Playground 中使用
下载它 然后摸索一下 看看有什么可用的 看看你如何在你的 App 中 使用 CryptoKit
我们会在明天的实验室中 解答你们的问题 我们期待你的反馈 谢谢 [掌声]
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。