Swift中CommonCrypto解密URLSession获取的AES128-CBC数据始终返回nil
解密失败的核心根因
你通过打印看到接口返回的字符串和自测加密结果一致,是视觉层面的等价,两者传递给解密函数的二进制数据本质完全不同:
- 自测环节
encrypt(string: "Hello")返回的dataEncrypt:是AES加密直接生成的原始密文二进制块。当你把这个原始密文做Base64编码时,才会展示成你看到的lG7Bqk0nwx732eOQLAzhqQ==字符串,这个原始密文没有经过额外编码,直接传入CCCrypt可以正常完成解密。 - 接口返回的Data:是服务端把原始密文经过Base64编码后生成的字符串对应的ASCII字节流。这部分Data存储的是组成Base64字符串的每个字符的编码值,不是AES算法要求的原始密文块,直接传给解密方法时,会因为密文格式不匹配导致CCCrypt执行失败,最终返回nil。
修复步骤
- 拿到接口返回的原始Data后,先完成两层转换:
- 把接口返回的Data转成UTF8字符串,拿到服务端返回的Base64格式密文
- 对Base64字符串做解码,得到AES算法可直接处理的原始密文二进制Data
- 将解码后的原始密文Data传入现有的解密方法即可正常解密
修正后的接口测试代码参考:
let aes128 = AES() if let url = URL(string: "\(localhostUrl)/payment") { URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, // 接口返回的UTF8字符串转原始Base64密文,同时清理可能存在的换行、空格 let base64Cipher = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines), // 将Base64字符串转成解密需要的原始密文Data let cipherData = Data(base64Encoded: base64Cipher) else { return } // 传入原始密文执行解密 let decryptResult = aes128?.decrypt(data: cipherData) print(decryptResult) // 可正常输出"Hello" }.resume() }
原有业务逻辑的调整提示
你原本的getTestAllPayments方法直接调用JSONDecoder解析接口返回的Data,因为完全跳过了「Base64解码 → AES解密 → 明文转JSON模型」的流程,即使接口返回数据正确,也无法解析出正常的[Payment]模型,需要在JSON解码前补上上述的Base64解码、AES解密步骤,把解密得到的明文Data传入JSONDecoder才能正常工作。
内容的提问来源于stack exchange,提问作者Kevin Kentie
相关产品推荐
相关产品推荐

