【发布时间】:2020-07-19 19:03:40
【问题描述】:
如果我能提供一些关于使用 Swift CryptoKit 进行数据加密的建议,我会非常有帮助。
目标
我想对一些数据进行 AES 加密,将其保存到应用程序包中,并在用户键入单独的密码后从应用程序中访问它。密码将单独分发,并以某种方式与对称密钥交互以解密数据。如果密码被泄露,我可以重新加密数据并使用新的加密数据更新应用程序包并分发新密码。
约束
- 数据必须包含在 app bundle 中,不能联网。
- TouchId 不可用。
- 如果可能,我想避免使用苹果密码系统。相反,我想在应用程序本身中要求输入密码,以便使用自定义密码条目。
我尝试过的
我在 Swift 中做了一个对称加密命令行程序。此 AES 对一些本地数据进行加密、保存并提供密钥。
let keyForData = SymmetricKey(size: .bits256)
do {
// Get the documents
let fileURLs = try fileManager.contentsOfDirectory(at: inputDirURL, includingPropertiesForKeys: nil)
for file in fileURLs {
if (file.pathExtension == "json"){
let fileName = String(file.path.split(separator: "/" ).last ?? "")
consoleIO.writeMessage("Processing \(fileName)")
let data = getData(file)
// Encrytion
let encryptedData = try! AES.GCM.seal(data, using: keyForData)
let encryptedDataFileURL = outputDirURL.appendingPathComponent(fileName + ".enc")
if let combinedData = encryptedData.combined {
try combinedData.write(to: encryptedDataFileURL)
consoleIO.writeMessage("File saved to \(encryptedDataFileURL.path.split(separator: "/" ).last ?? "")")
} else {
consoleIO.writeMessage("Problem daving encrypted file")
}
}
}
let keyString = keyForData.serialize()
let fileName = ".KEY_DO_NOT_COMMIT"
let encryptedKeyURL = outputDirURL.appendingPathComponent(fileName)
try keyString.write(to: encryptedKeyURL, atomically: false, encoding: .utf8)
consoleIO.writeMessage("Key saved to \(fileName)")
现在在设备包中我有加密的数据和密钥。
Apple 建议将密钥存储在钥匙串中。或者将其存储在 Secure Enclave 中。
这是我陷入最佳实践的地方。
实施思路
- 首次加载时将密钥保存在钥匙串中,然后删除密钥。 (这似乎不安全,并且没有将对称密钥与设备密码结合起来。)
- 将密码传递给命令行应用程序,使用它来“加扰”对称密钥,然后将对称密钥保存到钥匙串并在用户输入应用程序密码时“解扰”。 (这似乎有道理,但我不确定如何在 Swift 中使用字符串“加扰”对称密钥。)
- 首次加载时,使用密码和对称密钥以某种方式在 Secure Enclave 中创建密钥对。在未来打开应用程序时,密码提供对称密钥。这个问题似乎是 Secure Enclave 从不要求存储密钥的一部分,它只是提供了一个密钥对来使用,但在我的情况下,一半的密钥对已经存在。
如果您的回答是“去学习加密操作”,我理解。老实说,我已经阅读了几篇文章:Generating New Cryptographic Keys、CryptoKit and Secure Enclave、Common CryptoKit operation,但我看不到涉及密码的用例。对于正确方向的观点,我将不胜感激。
这里的关键是我想要在加密时选择的密码与加密密钥进行交互。如果该加密密钥可以存储在 Secure Enclave 中,那将是锦上添花。
【问题讨论】:
标签: ios swift encryption