You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过密码生成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 10:35:05