如何通过密码生成CryptoKit的SymmetricKey?遇密钥大小错误
问题分析与修复:SymmetricKey密码初始化的密钥大小错误
错误核心原因
你代码里有两个关键问题导致了CryptoKitError error 1(密钥大小不匹配):
- 编码格式混淆:你把SHA256哈希的十六进制字符串当成Base64编码去解码,这完全不符合数据格式要求。
- 不必要的字符串转换:将原始哈希二进制数据转成十六进制字符串后,再试图把这个字符串当作Base64解码,得到的数据长度完全不是SymmetricKey需要的32字节(256位)。
哈希显示差异的原因
你看到的两个哈希本质是同一类数据的不同编码形式:
- 从密码生成的
5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5是SHA256哈希的十六进制字符串(每个字节用两个十六进制字符表示,共64个字符)。 .bits256对应的cfyk1v2dRIlVKHlpy8qBH71v4BXGSUHPUS3wLn1gzj0=是SHA256哈希的Base64字符串(直接把32字节的原始二进制数据转成Base64,共44个字符左右)。
你错误地把十六进制字符串当作Base64去解码,得到的不是需要的32字节密钥,自然会触发密钥大小错误。
修正后的代码
直接使用SHA256哈希的原始二进制数据初始化SymmetricKey,去掉多余的十六进制转换:
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 passData = pass.data(using: .utf8) else { return nil } // 直接将SHA256哈希的原始二进制数据转为Data let hashedData = Data(SHA256.hash(data: passData)) self.init(data: hashedData) } }
额外最佳实践
直接用密码的哈希作为对称密钥安全性不足,建议使用密钥派生函数(KDF),比如HKDF或PBKDF2,加入盐值和迭代次数来增强安全性:
// 带盐值的安全密钥派生示例 init?(pass: String, salt: Data) { guard let passData = pass.data(using: .utf8) else { return nil } let derivedKey = HKDF<SHA256>.deriveKey( inputKeyMaterial: SymmetricKey(data: passData), salt: salt, info: Data() // 可根据业务场景添加自定义信息 ) self.init(data: derivedKey.withUnsafeBytes { Data($0) }) }
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

