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

.NET C#解密AES加密数据报错:无效Base64字符串问题排查

AES跨语言加密解密问题(Angular CryptoJS → C# RijndaelManaged)

我在.NET C#应用中解密AES加密数据时遇到问题:使用Angular的CryptoJS库加密JSON对象,再通过C#的RijndaelManaged类解密,触发错误提示:

输入不是有效的Base-64字符串,因为它包含非Base64字符、填充字符超过两个,或填充字符中存在非法字符

奇怪的是,仅加密较大数据(如JSON对象)时会触发该错误,加密“welcome”这类小文本则正常。已确认两端的key和IV完全一致,怀疑问题与编码、传输或填充规则有关,但无法定位具体原因。

示例:

  • 加密{id: 1, name: "test"}得到结果:+IhryRiKnNFiOWNv3cnWde97CiTZZLtVPMbnIm5ieDg=
  • 加密“hello”得到结果:v8FQU3S6MnFlkSK349fZUQ==

Angular端加密代码

const key = CryptoJS.enc.Utf8.parse('4512631236589784');
const iv = CryptoJS.enc.Utf8.parse('4512631236589784');
const data = {id: 1, name: "test"};
const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(JSON.stringify(data)), key, {
    keySize: 128 / 8,
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});
console.log('Encrypted : ' + encrypted);

C#端解密代码

public string DecryptData()
{
    try
    {
        var token = HttpContext.Request.Query["token"];
        var keybytes = Encoding.UTF8.GetBytes("4512631236589784");
        var iv = Encoding.UTF8.GetBytes("4512631236589784");

        var encrypted = Convert.FromBase64String(token);
        var decryptedFromJavascript = DecryptStringFromBytes(encrypted, keybytes, iv);
        return decryptedFromJavascript;
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return e.Message;
    }
}

private string DecryptStringFromBytes(byte[] cipherText, byte[] key, byte[] iv)
{
    // Check arguments.
    if (cipherText == null || cipherText.Length <= 0) 
    {
        throw new ArgumentNullException("cipherText");
    }

    if (key == null || key.Length <= 0) 
    {
        throw new ArgumentNullException("key");
    }

    if (iv == null || iv.Length <= 0) 
    {
        throw new ArgumentNullException("key");
    }

    // Declare the string used to hold
    // the decrypted text.
    string plaintext = null;

    // Create an RijndaelManaged object
    // with the specified key and IV.
    using (var rijAlg = new RijndaelManaged())  
    {
        //Settings
        rijAlg.Mode = CipherMode.CBC;
        rijAlg.Padding = PaddingMode.PKCS7;
        rijAlg.FeedbackSize = 128;

        rijAlg.Key = key;
        rijAlg.IV = iv;

        // Create a decrytor to perform the stream transform.
        var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

        try 
        {
            // Create the streams used for decryption.
            using(var msDecrypt = new MemoryStream(cipherText)) 
            {
                using(var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
                {
                    using(var srDecrypt = new StreamReader(csDecrypt)) 
                    {
                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        } 
        catch 
        {
            plaintext = "keyError";
        }
    }

    return plaintext;
}

问题原因分析

  1. URL传输的Base64字符解析问题:
    加密后的Base64字符串包含+、=等特殊字符时,通过URL查询参数传输会被自动解析:+会被替换为空格,长字符串还可能因URL长度限制被截断,导致C#端接收到的字符串不是完整有效的Base64格式。小文本加密结果可能刚好不包含这些特殊字符,或长度足够短,因此能正常传输。

  2. CryptoJS结果序列化的隐含问题:
    CryptoJS的AES.encrypt返回的是CipherParams对象,直接转为字符串时虽然默认输出Base64,但部分场景下可能存在编码偏差,或在跨环境传输时出现格式丢失。

解决建议

1. Angular端做URL安全处理

明确获取Base64密文并进行URL编码,避免特殊字符被解析:

// 明确获取标准Base64密文
const encryptedBase64 = encrypted.toString(CryptoJS.format.OpenSSL);
// 对密文做URL编码
const urlSafeEncrypted = encodeURIComponent(encryptedBase64);
console.log('URL Safe Encrypted : ' + urlSafeEncrypted);

2. C#端先解码再解析Base64

接收查询参数后先做URL解码,再转换为字节数组:

var token = HttpContext.Request.Query["token"];
// 解码URL编码后的字符串
var decodedToken = Uri.UnescapeDataString(token);
var encrypted = Convert.FromBase64String(decodedToken);

3. 改用POST请求传递密文

如果加密数据较大,建议将密文放在POST请求体中传递,避免URL查询参数的长度限制和字符解析问题。

4. 修复C#端的参数校验错误

DecryptStringFromBytes方法中IV的空校验错误抛出了ArgumentNullException("key"),应修正为:

if (iv == null || iv.Length <= 0) 
{
    throw new ArgumentNullException("iv");
}

内容的提问来源于stack exchange,提问作者Himanshu Rahi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:52:51