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

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;
}

解决思路与修正代码

核心要点

  1. AES-GCM是认证加密模式,和传统CBC模式不兼容,C#需使用专门的AesGcm类(.NET Core 3.0及以上版本支持)。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:35:20