iOS CryptoKit加密与.NET Core C#解密的IV长度适配问题求助
iOS CryptoKit AES-GCM加密与.NET Core C#解密适配方案
问题描述
iOS端使用CryptoKit的AES.GCM加密数据后,传递到.NET Core后端解密时触发错误:Specified initialization vector (IV) does not match the block size for this algorithm.。本质原因是iOS用的是AES-GCM模式(配套12字节nonce),而C#原代码使用传统Aes类(默认CBC模式,要求16字节IV),加密模式不匹配导致IV长度校验失败。
iOS加密代码
class Security { static let keyStr = "d5a423f64b607ea7c65b311d855dc48f" // 32字节AES-256密钥 static let iv="31348c0987c7" // 12字节GCM nonce class func encode(_ text:String)->String { let key=SymmetricKey(data: Security.keyStr.data(using: .utf8)!) let nonce=try! AES.GCM.Nonce(data: iv.data(using: .utf8)!) let encrypted=try! AES.GCM.seal(text.data(using: .utf8)!, using: key, nonce: nonce) return encrypted.combined!.base64EncodedString() } }
原C#解密代码(存在问题)
public string decrypt(string encryptedText) { string keyStr = "d5a423f64b607ea7c65b311d855dc48f"; string iv = "31348c0987c7"; string plaintext = ""; Debug.WriteLine(encryptedText); using (Aes aesAlg = Aes.Create()) { Debug.WriteLine(AesGcm.IsSupported); var key = System.Text.Encoding.UTF8.GetBytes(keyStr); var iV = System.Text.Encoding.UTF8.GetBytes(iv); aesAlg.Key = key; aesAlg.IV = iV; // 此处报错:IV长度不符合CBC模式要求 ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(request.pswd))) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { plaintext = srDecrypt.ReadToEnd(); } } } } Debug.WriteLine(plaintext); return plaintext; }
解决思路与修正代码
核心要点
- AES-GCM是认证加密模式,和传统CBC模式不兼容,C#需使用专门的
AesGcm类(.NET Core 3.0及以上版本支持)。 - iOS端
encrypted.combined的结构固定为:[12字节nonce] + [密文] + [16字节认证标签],解密时必须拆分这三部分分别处理。
修正后的C#解密代码
using System; using System.Security.Cryptography; using System.Text; public string Decrypt(string encryptedText) { string keyStr = "d5a423f64b607ea7c65b311d855dc48f"; byte[] key = Encoding.UTF8.GetBytes(keyStr); // 解码Base64格式的加密数据 byte[] combinedData = Convert.FromBase64String(encryptedText); // 拆分nonce、密文、标签 const int nonceSize = 12; const int tagSize = 16; byte[] nonce = new byte[nonceSize]; byte[] ciphertext = new byte[combinedData.Length - nonceSize - tagSize]; byte[] tag = new byte[tagSize]; Buffer.BlockCopy(combinedData, 0, nonce, 0, nonceSize); Buffer.BlockCopy(combinedData, nonceSize, ciphertext, 0, ciphertext.Length); Buffer.BlockCopy(combinedData, nonceSize + ciphertext.Length, tag, 0, tagSize); // 使用AesGcm执行解密 byte[] plaintextBytes = new byte[ciphertext.Length]; using (var aesGcm = new AesGcm(key)) { aesGcm.Decrypt(nonce, ciphertext, tag, plaintextBytes); } return Encoding.UTF8.GetString(plaintextBytes); }
额外注意事项
- 确保.NET Core版本≥3.0,
AesGcm类才会被支持。 - 生产环境中不建议硬编码nonce,建议每次加密生成随机12字节nonce,CryptoKit的
combined字段会自动包含nonce,无需额外传递。 - 密钥长度为32字节(对应AES-256),两端需保持完全一致,避免编码差异。
内容的提问来源于stack exchange,提问作者matyasl
相关产品推荐
相关产品推荐

