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

使用BouncyCastle C#库实现AES加解密失败,无法还原原文本求助

AES-CTR加解密失败问题排查与修复(Bouncy Castle C#)

你的代码存在三个核心逻辑错误,直接导致解密无法还原原始文本:

1. 解密输入处理错误

解密时,输入是经过URL安全Base64编码的密文,你先还原了-/_为+//,但错误地用Encoding.UTF8.GetBytes()将其转成字节数组——密文是二进制数据,不是UTF8编码的字符串,正确做法是用Convert.FromBase64String()解码还原后的Base64字符串,得到密文字节数组。

2. 密码器初始化模式错误

不管加密还是解密,你都调用cipher.Init(true, ...),其中true代表加密模式。解密时必须将第一个参数改为false,否则会把密文当成明文再次加密,完全偏离预期。

3. 解密输出处理错误

解密得到的是原始明文的UTF8字节数组,你却将其转成Base64字符串返回,正确做法是直接将解密后的字节数组转成UTF8字符串。


修正后的完整代码

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text;

static string Encrypt(string keyString, string input)
{
    // 密钥处理:SHA256哈希生成256位密钥
    var keyBytes = Encoding.UTF8.GetBytes(keyString);
    var sha256 = new Sha256Digest();
    sha256.BlockUpdate(keyBytes, 0, keyBytes.Length);
    var keyBytesPadded = new byte[sha256.GetDigestSize()];
    sha256.DoFinal(keyBytesPadded, 0);

    // 生成随机IV(CTR模式必须用唯一IV,这里用随机保证安全性)
    var iv = new byte[16];
    new SecureRandom().NextBytes(iv);

    // 初始化AES-CTR加密器
    var cipher = CipherUtilities.GetCipher("AES/CTR/NoPadding");
    cipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", keyBytesPadded), iv));

    // 加密明文
    var inputBytes = Encoding.UTF8.GetBytes(input);
    var encryptedBytes = cipher.DoFinal(inputBytes);

    // 将IV和密文拼接(解密时需要用同一个IV),再转URL安全Base64
    var combinedBytes = new byte[iv.Length + encryptedBytes.Length];
    Buffer.BlockCopy(iv, 0, combinedBytes, 0, iv.Length);
    Buffer.BlockCopy(encryptedBytes, 0, combinedBytes, iv.Length, encryptedBytes.Length);
    
    var base64 = Convert.ToBase64String(combinedBytes);
    return base64.Replace("+", "-").Replace("/", "_");
}

static string Decrypt(string keyString, string input)
{
    // 还原URL安全Base64为标准Base64
    var standardBase64 = input.Replace("-", "+").Replace("_", "/");
    var combinedBytes = Convert.FromBase64String(standardBase64);

    // 拆分IV和密文(IV长度16字节)
    var iv = new byte[16];
    var encryptedBytes = new byte[combinedBytes.Length - iv.Length];
    Buffer.BlockCopy(combinedBytes, 0, iv, 0, iv.Length);
    Buffer.BlockCopy(combinedBytes, iv.Length, encryptedBytes, 0, encryptedBytes.Length);

    // 密钥处理:和加密时一致的SHA256哈希
    var keyBytes = Encoding.UTF8.GetBytes(keyString);
    var sha256 = new Sha256Digest();
    sha256.BlockUpdate(keyBytes, 0, keyBytes.Length);
    var keyBytesPadded = new byte[sha256.GetDigestSize()];
    sha256.DoFinal(keyBytesPadded, 0);

    // 初始化AES-CTR解密器(注意第二个参数是false)
    var cipher = CipherUtilities.GetCipher("AES/CTR/NoPadding");
    cipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", keyBytesPadded), iv));

    // 解密密文,转成明文字符串
    var decryptedBytes = cipher.DoFinal(encryptedBytes);
    return Encoding.UTF8.GetString(decryptedBytes);
}

const string key = "supersecret";
const string message = "hello world!";

// 测试验证
var encrypted = Encrypt(key, message);
var decrypted = Decrypt(key, encrypted);
Console.WriteLine(decrypted == message); // 输出True

额外提醒:原代码里加密和解密用的是固定全0的IV,这在CTR模式下非常危险——重复使用相同IV和密钥会导致加密完全失效。修正后的代码改用随机生成IV,并将IV和密文一起传输,这是CTR模式的标准安全做法。

内容的提问来源于stack exchange,提问作者Node.JS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:12:54