CryptoKit基础知识:端到端加密
对于开发应用程序的公司和开发人员来说,安全性是一个至关重要的问题,尤其是在医疗领域,数据泄露的后果极其严重。而端到端加密正是在这种情况下发挥作用。
在本指南中,您将学习如何使用 Apple 自家的CryptoKit框架,在您的 Swift 应用程序中为 iOS、macOS、其他 Apple 产品甚至 Linux 实现基本的端到端加密流程。
CryptoKit是什么?
CryptoKit 是一个新的 Swift 框架,它使执行加密操作比以往任何时候都更加容易和安全,无论您只是需要计算哈希值还是正在实现更高级的身份验证协议。
什么是端到端加密?
端到端加密是一种通信系统,只有通信双方才能读取消息。任何窃听者都无法获取解密对话所需的加密密钥——即使是运营该通信服务的公司也不行。
你需要什么
CryptoKit可在以下平台上使用:
- iOS 13.0+
- macOS 10.15 及更高版本
- Mac Catalyst 13.0+
- tvOS 13.0+
- watchOS 6.0+
- Linux(如Swift Crypto)
步骤 1:生成密钥对
加密密钥对是端到端加密的核心:公钥用于加密他人的数据,私钥用于解密他人加密的数据。应用程序中的每个用户都应该拥有一个密钥对,其公钥存储
在可信服务中供其他用户获取,而私钥则安全地存储在用户设备上。可信服务可以使用 Swift和Vapor框架编写,也可以使用您选择的其他语言和框架。
我们首先生成一个私钥,然后从中提取出对应的公钥,并将其发送给可信服务。本指南将使用Curve25519算法,但其他算法的操作方法也类似。
import CryptoKit
// generate key pair
let privateKey = Curve25519.KeyAgreement.PrivateKey()
let publicKey = privateKey.publicKey
// publish public key in trusted service
TrustedService.publishKey(publicKey, for: myIdentity)
公钥具有一个var rawRepresentation: Data属性,可用于将其序列化为受信任服务的有效负载。
步骤二:数据加密
要加密用户(接收者)的数据,首先需要从受信任的服务中获取他们的公钥。
let recipientPublicKey = TrustedService.fetchPublicKey(of: recipientIdentity)
初始化程序Curve25519.KeyAgreement.PublicKey(rawRepresentation: Data)可用于反序列化来自受信任服务的公钥。
步骤 2.1:导出对称密钥
公钥不能直接用于加密数据。通信双方使用公钥通过Diffie-Hellmann 密钥协商来协商一个用于加密的对称密钥。为此,我们将使用发送方的私钥和接收方的公钥生成一个共享密钥,然后使用HKDF密钥派生函数从该共享密钥派生出对称密钥。
let sharedSecret = try! privateKey.sharedSecretFromKeyAgreement(with: recipientPublicKey)
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self,
salt: protocolSalt,
sharedInfo: Data(),
outputByteCount: 32)
协议盐值会影响对称密钥派生的结果。请选择一个在您的使用场景中保持不变的值,例如:"My Key Agreement Salt".data(using: .utf8)!
步骤 2.2:使用对称密钥加密数据
现在,我们终于可以使用这个对称密钥进行加密了。CryptoKit 支持的多种加密算法都可以完成这项工作。在本指南中,我们将使用ChaChaPoly 算法,根据Adam Langley和其他研究人员的说法,它在移动设备上的速度可以比 AES 快三倍。
let sensitiveMessage = "The result of your test is positive".data(using: .utf8)!
let encryptedData = try! ChaChaPoly.seal(sensitiveMessage, using: symmetricKey).combined
现在encryptedData可以安全地将邮件发送给收件人了。
步骤 3:解密数据
要解密接收到的数据,接收方需要导出用于加密数据的同一对称密钥。但在导出该密钥之前,我们需要发送方的公钥。
let senderPublicKey = TrustedService.fetchPublicKey(of: senderIdentity)
步骤 3.1:导出对称密钥
为了导出对称密钥,我们将执行与步骤 2.1 中相同的过程,只是这次我们将使用接收方的私钥和发送方的公钥。这将使我们能够重新生成共享密钥,该密钥可用于导出相同的对称密钥。
let sharedSecret = try! privateKey.sharedSecretFromKeyAgreement(with: senderPublicKey)
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self,
salt: protocolSalt,
sharedInfo: Data(),
outputByteCount: 32)
我们刚刚在用户之间共享了一个对称密钥,而这个密钥从未存在于用户设备之外!🤯
步骤 3.2:使用对称密钥解密数据
现在我们可以使用对称密钥来解密数据。
let sealedBox = try! ChaChaPoly.SealedBox(combined: encryptedData)
let decryptedData = try! ChaChaPoly.open(sealedBox, using: symmetricKey)
let sensitiveMessage = String(data: decryptedData, encoding: .utf8)
print(sensitiveMessage) // "The result of your test is positive"
端到端加密已实现!
敬请关注
本指南中描述的过程保证了一件事:加密。这意味着只有用户本人才能解密为该用户加密的数据。
无法保证:身份验证和完整性。这意味着您无法确定加密数据是否来自特定人员,也无法确定数据在传输过程中是否被篡改。因此,您容易受到某些形式的中间人攻击。
此外,前向保密性也无法得到保证。这意味着,如果私钥泄露,所有为该密钥所有者加密的数据都可能被解密,直到他们开始使用新密钥为止。提供前向保密性的方案使用一次性密钥,即使密钥被盗或破解,也只会泄露部分数据。
为了确保身份验证和完整性,我们将在后续文章中深入探讨 CryptoKit 创建和验证签名的功能。敬请期待!
额外内容
Swift Playground
我上传了一个 Swift Playground 到 GitHub,它大致遵循本文所述的流程,只是省略了 TrustedService。这是链接。别忘了给它点个赞哦!
将私钥安全地存储在设备上
苹果建议使用设备的钥匙串。本指南对此有详细说明。
什么是Swift Crypto?
Swift Crypto 是 Apple CryptoKit API 的一个开源实现,适用于 Linux 平台。它使跨平台或服务器应用程序能够充分利用 CryptoKit 的优势。
发现任何错误吗?
虽然我有一些端到端加密方面的行业经验,但我并不认为自己是专家。如有任何疑问,请通过matheus@cardo.so联系我,或者通过推特@cardosodev私信我。
免责声明:本文或系列文章仅供教育用途,不建议在未咨询专业人士的情况下使用。
文章来源:https://dev.to/cardoso/cryptokit-basics-end-to-end-encryption-1d6d