Swift使用CryptoKit加密每次输出结果不一致问题排查
问题原因
- 你观察到的加密结果不一致是AES-GCM模式的正常安全设计,不是代码bug。
- AES-GCM加密要求同一个密钥下每次使用的nonce(初始化向量)全局唯一,CryptoKit的
AES.GCM.seal(_:using:)方法默认会自动生成随机的12字节nonce,所以就算明文、密钥完全相同,每次加密的输出也会不同。 - 你返回的
sealedBox.combined已经将随机nonce、密文、校验标签拼接为完整数据,解密时直接传入该数据即可正常还原明文,不需要单独存储nonce。
补充说明
如果业务场景确实需要相同输入得到相同加密结果,你可以手动指定nonce,但必须明确如下风险:
同一个密钥+nonce组合只能使用一次,重复使用会直接导致AES-GCM的安全性完全失效,攻击者可以轻松推导出密钥和明文,生产环境绝对不能使用固定nonce。
手动指定nonce的示例代码:
// 仅用于测试场景,生产环境禁止使用固定nonce func encryptWithFixedNonce(password: String, input: [UInt8]) throws -> Data { let pwd = password.padding(toLength: 32, withPad: "@", startingAt: 0) let key = SymmetricKey(data: pwd.data(using: .utf8)!) // 手动构造固定nonce,12字节是AES-GCM推荐的标准长度 let fixedNonce = try AES.GCM.Nonce(data: Data([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c])) let sealedBox = try AES.GCM.seal(input, using: key, nonce: fixedNonce) return sealedBox.combined! }
调用上述方法时相同输入就会得到相同输出。
内容的提问来源于stack exchange,提问作者Russ
相关产品推荐
相关产品推荐

