WWDC2019:Cryptography and Your Apps

WWDC2019 Session 709 : Cryptography and Your Apps

上面是 session 视频是 WWDC 关于密码学与 App 信息防护方面的一节 ,大概 40 min,整个视频分为两部分,重点介绍了在 App 的开发中,apple 针对用户信息安全方面所做的努力,以及全新的 swift 安全加密框架。

通过这个视频我们可以进一步的思考一下,如何把我们的 App 在安全层面做的更好。首先就先看一下当下这个最新的加密框架~ CryptoKit ~

全新的 Swift 安全加密框架 CryptoKit

初识 CryptoKit

你是否厌烦大量的 C Api 去进行加密解密?

你是否厌烦了每次 C Api 都要 开辟特定 size 的 buffer ?

你是否厌烦了在 C Api 里,为了类型安全以及 Null 判断,要编写大量繁重的代码?

你是否厌烦了在完成一整个加密解密操作后,还需要清零&释放 buffer ?

你是否研发了 C Api 下烦躁的内存管理?

那你还在等什么!快点拥抱最新的 CryptoKit 吧!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Generating and releasing a cryptographic key for a C Crypto API
let keyByteCount = 256/8
var key = Array(repeating: 0, count: keyByteCount)
let err = SecRandomCopyBytes(kSecRandomDefault, keyByteCount, &key)
if (err != errSecSuccess) {
// Safely handle the error
}
// Use the Key
...
// Zeroize the key
memset_s(&key, keyByteCount, 0, keyByteCount)

// ============================

// Generating and releasing a cryptographic key with Apple CryptoKit
let key = SymmetricKey(size: .bits256)

一行代码就是爽~ CryptoKit 顶呱呱!~

看看这代码对比差距,CryptoKit 不仅大幅度简化了 Api 的使用,还支持

  • 强类型的 Api 设计
  • 自动化的内存管理
  • 完善的一致性检验

CryptoKit 的架构设计与详解

CryptoKit 整体架构如图

  • Hash Function 哈希 Api
  • Symmetric-Key Cryptography 对称加密
  • Public-Key Cryptography 非对称加密
  • Insecure Module 已经被废弃的加密算法( MD5 ,SHA1 )

HASH API

1
2
let audioData = FileManager.default.contents(atPath: filePath)!
let digest = SHA256.hash(data: audioData)

以上便是一个最简单的 Hash 过程的 Api 示例,Hash 了一个 Data 文件~

对称加密解密

最基本的对称加密流程如下:

  • 服务器对数据进行对称加密
  • 密钥存储在客户端
  • 加密数据通过网络传输给客户端
  • 使用密钥解密还原数据
1
2
3
4
5
6
7
8
// Initialize the decryption key
let key = SymmetricKey(data: keyData)
// Initialize the sealed box
guard let sealedBox = ChaChaPoly.SealedBox(combined: downloadedData) else {
throw MapDownloaderError.invalidDownload
}
// Open the sealed box (authenticates + decrypts)
let mapData = try ChaChaPoly.open(sealedBox, using: key)

上面就是一个客户端解密的过程,使用了 ChaChaPoly 这个比较新的加密算法,可以看到 API 封装了算法,用这个 CryptoKit 可以更方便的直接解密。其实框架还有很多其他现成可用的加解密算法框架,里面也包括我们最熟悉的 AES ~

非对称签名

除了对称加密解密,还有很重要的非对称签名也是被广泛运用在信息授权,数据防篡改上,在这块 CryptoKit 依然能很方便快捷的带你完成相关操作

非对称签名的整体流程大致如下

  • 手机生成私钥 + 公钥
  • 公钥保存在服务器
  • 用私钥 + 传输数据,生成签名
  • 签名&数据 发给服务器
  • 服务器用公钥验证签名
1
2
3
4
5
6
7
// Generate private key and register public key with server
let privateKey = P256.Signing.PrivateKey()
let publicKeyData = privateKey.publicKey.compactRepresentation!
// Store privateKey in Keychain
...
// Signing content
let signature = try privateKey.signature(for: transactionData)

上面的示例代码就向你展示了在客户端这一侧,如何使用 CryptoKit 的 Api ,生成私钥,生成公钥,对数据完成签名,代码非常的简洁~

用户授权与安全验证

不仅如此,在使用 CrytoKit 在对用户数据进行安全处理,加密解密的时候,还可以进一步使用 apple 的生物识别验证等能力,来保证用户在主动授权的情况下,才允许对数据进行加密与解密操作

1
2
3
4
5
6
7
8
9
let accessControl = SecAccessControlCreateWithFlags(nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage, .userPresence],
nil)!
let authContext = LAContext()
authContext.touchIDAuthenticationAllowableReuseDuration = 10
authContext.localizedReason = "Authorizing $10 transfer to Bob."
let privateKey = try SecureEnclave.P256.Signing.PrivateKey(accessControl: accessControl
authenticationContext: authContext)

可以看到,在生成 PrivateKey 的时候,引入 LocalAuthentication 和 SecureEnclave 来限制私钥的使用条件。

  • 可以通过 accessControl 来控制私钥只允许在 Unlocked 状态下生成与使用
  • 也可以通过 LocalAuthentication 来对使用私钥时候进行
    • 指纹 ID 验证
    • Face ID 验证
    • Apple ID 密码 验证

可以看到 CryptoKit 与 LocalAuthentication 两个框架可以衔接起来全面加强用户信息与数据的安全保护

性能

在性能方面,CryptoKit 基于 corecrypto 之上封装,其中包含一些手动优化后的汇编代码,所以整体性能也比较好。

如何全方位的加强对用户信息与数据的保护

单纯运用密码学框架 CryptoKit 提供的各种 Api 来对极其敏感的支付及隐私数据进行加密解密,这还远远不够。用户在 App 的使用之中会产生很多很多的数据,这些数据可能并不直接关系到隐私与金钱支付,但也属于用户的数据,值得被开发者保护起来

apple 是一家极其注重用户隐私的公司,除了 CryptoKit 在 App 开发中的各种层面都提供了很多安全防护的能力,只要善加利用,开发者就能加强自己 App 的安全等级与防护能力

数据存储安全

我们经常会使用 File Api 来把数据存储到沙盒之中,简简单单的 write 就可以实现,但在这 Api 里,apple 也提供了深层的安全保护配置 completeFileProtection ,来强化数据安全

1
2
3
4
5
6
do {
try data.write(to: fileURL, options: .completeFileProtection)
}
catch {
// Handle errors
}

这么简单的一个配置可以实现如下的能力:

  • 通过用户的密码来对数据进行保护
  • 设备密码被盗,加密数据被盗,用户修改了密码,数据无法用旧密码恢复
  • 支持只有当用户解锁屏幕时,才可以访问加密数据
  • 支持多种文件类型
  • 防止暴力破解

授权与密钥

apple 建议,不要使用 UserDefault or File 来保存用户登录授权的 token 以及密钥信息,应该使用 KeyChain

  • KeyChain 支持本地存储与云端 iCloud 同步
  • Keychain 存储不仅支持上文所有提到的文件数据存储的能力,还支持更多

apple 还提供 LocalAuthentication 的用户授权,来进一步保护 KeyChain 数据,通过调用 LocalAuthentication 框架来要求用户进行

  • 指纹 ID 验证
  • Face ID 验证
  • apple Watch 验证( 新增:macOS上可以用手表进行认证 )

跨设备数据共享

1
2
3
4
5
6
// Save the contents of a given fileURL to a per-user location
let asset = CKAsset(fileURL: ...)
let record: CKRecord = ...
record["AssetField"] = asset
let database = CKContainer.default().privateCloudDatabase
database.save(record) { ... }

apple 提供了 CloudKit 从而实现,加密的安全的私有云端数据库,可以实现

  • 不需要用户登录 App ,就可以实现数据的云端存储(需要登录 AppleID)
  • 可以分享给其他用户,并且可以进行权限管控

安全网络链接

为了保证与自己服务器的网络连接安全可靠,完全使用自定义的网络传输协议确实是一个可行的选择,但其实 apple 还提供了两个框架可以方便用户进行安全的网络链接,这两套都是默认使用 TLS 安全协议,并且支持 TLS 1.3

  • Network Framework 去年 WWDC 介绍过得网络框架
  • URLSession Api
1
2
3
4
5
6
7
8
9
10
11
// With Network Framework
let conn = NWConnection(host: "imap.mail.me.com", port: .imaps, using: .tls)
conn.start(queue: .main)
// With URLSession
let url = URL(string: "https://www.apple.com")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
// Handle error
}
// Operation on data
}

自定义证书

apple 提供了 secTrust Api 可以支持异步的对自签名自定义证书进行认证

1
2
3
4
5
6
7
8
9
// Evaluate a certificate validity asynchronously and with legible errors
SecTrustEvaluateAsyncWithError(trust, queue) { (trust, success, error) in
if (success) {
let publicKey = SecTrustCopyPublicKey(trust);
// Use key…
} else {
// Handle errors
}
}

感受

已经不知道多少次,apple 在 WWDC 添加对用户信息数据的安全防护,对用户隐私追踪的手段限制。这次 WWDC 苹果更进一步的引导所有开发者来强化对用户数据的保护,并且把安全的基础能力上植入到日常使用的 存储/网络/共享/授权 等多套日常开发框架之中,再加上更强大更易用的 CryptoKit,有理由相信苹果在用户安全方面所做的努力和下的决心