我有以下代码:
public extension SymmetricKey {
init?(base64Encoded base64EncodedKeyString: String) {
guard let keyData = Data(base64Encoded: base64EncodedKeyString) else { return nil }
self.init(data: keyData)
}
var base64: String {
self.withUnsafeBytes { body in
Data(body).base64EncodedString()
}
}
init?(pass: String) {
guard let passHash = passToHash(pass: pass) else { return nil }
self.init(base64Encoded: passHash)
}
}
fileprivate func passToHash(pass: String) -> String? {
guard let passData = pass.data(using: .utf8) else { return nil }
let hashed = SHA256.hash(data: passData)
return hashed.compactMap { String(format: "%02x", $0) }.joined()
}
问题是如果我尝试使用,SymmetricKey
我会看到错误:
操作无法完成。(CryptoKit.CryptoKitError 错误 1。)
此错误意味着密钥大小不正确。
如果我尝试比较SymmetricKey
使用默认方式生成的 s 和从我的自定义初始化生成的 s ,我会看到差异:
5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5 //from password
cfyk1v2dRIlVKHlpy8qBH71v4BXGSUHPUS3wLn1gzj0= //.bits256
我做错了什么?为什么哈希看起来不一样?
首先,这是一个非常不安全的密钥派生函数。任何严肃的加密方案都不应该使用它。要从密码创建密钥,必须使用 PBKDF(基于密码的密钥派生函数),例如 PBKDF2。
出于兼容性目的,您可能需要实施这个有缺陷的方案,因此我将在这里深入研究它。
密钥从根本上来说就是数据。您创建了一个十六进制编码的字符串,然后对其进行了 Base64 编码。这使得生成的数据长度是应有长度的两倍。您的意思是:
不幸的是,Apple 的 CryptoKit 不包含任何适当的 PBKDF。它是一个非常有限的框架,仅为某些非常特定的用例提供原语。一些提供您所需工具的流行框架是CryptoSwift和IDZSwiftCommonCrypto。更通用的方法是使用 Apple 的 CommonCryptor,但它在 Swift 中并不是特别有趣。
但这里有一个例子。
调用此方法需要传递一个盐。如何选择盐取决于您的用例。一种常见的情况是每次加密时都使用一个随机盐(例如 16 字节),然后将盐与加密数据一起传递,以便接收方可以解密。以下是制作这种随机数据的方法:
您还可以在上述框架中获得执行这些操作的函数。在 Swift 中进行加密几乎没有什么乐趣。