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

关于AES加密Byte[]在HttpRequest头传递及编码的技术问询

技术问题:AES加密结果的编码与请求头传输问题

场景与代码实现

我尝试创建一个会话,会话内容为经AES密钥加密的随机字符串,加密结果以byte[]形式返回。相关代码如下:

CryptoService类

public class CryptoService : ICryptoService
{
    const int PASSWORD_LENGTH = 32;
    private static Encoding encoder = Encoding.UTF8;

    public byte[] EncrpyRandomPassword(string nonceValue)
    {
        var randomString = RandomPasswordGenerator.RandomString(PASSWORD_LENGTH);

        var keyByte = encoder.GetBytes(nonceValue);
        using Aes myAes = Aes.Create();

        byte[] encrypted = EncryptStringToBytes_Aes(randomString, keyByte, myAes.IV);

        return encrypted;
    }
}

Session类与接口

public interface ISession
{
    byte[] SessionKey { get; }
    string SessionKeyASCI { get; }
    string SessionKeyUTF8 { get; }
    bool IsValid { get; }
    void ValidateSession();
}

public class Session : ISession
{
    private byte[] m_SessionKey;
    private bool m_IsValid;

    public byte[] SessionKey => m_SessionKey;

    public bool IsValid => m_IsValid;

    public string SessionKeyASCI => Encoding.ASCII.GetString(m_SessionKey);

    public string SessionKeyUTF8 => Encoding.UTF8.GetString(m_SessionKey);
}

控制器代码

public async Task<IActionResult> CreateSessionAsync(string nonceValue)
{
    if (string.IsNullOrEmpty(nonceValue))
    {
        throw new ArgumentException($"'{nameof(nonceValue)}' cannot be null or empty.", nameof(nonceValue));
    }
    var session = await _sessionProvider.CreateSession(nonceValue);

    return Ok(session);
}

AES加密方法

static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
    // Check arguments.
    if (plainText == null || plainText.Length <= 0)
        throw new ArgumentNullException("plainText");
    if (Key == null || Key.Length <= 0)
        throw new ArgumentNullException("Key");
    if (IV == null || IV.Length <= 0)
        throw new ArgumentNullException("IV");
    byte[] encrypted;

    // Create an Aes object
    // with the specified key and IV.
    using (Aes aesAlg = Aes.Create())
    {
        aesAlg.Key = Key;
        aesAlg.IV = IV;

        // Create an encryptor to perform the stream transform.
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

        // Create the streams used for encryption.
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {
                    //Write all data to the stream.
                    swEncrypt.Write(plainText);
                }
                encrypted = msEncrypt.ToArray();
            }
        }
    }

    // Return the encrypted bytes from the memory stream.
    return encrypted;
}

Postman返回结果

{
    "sessionKey": "lI+ZRpzqP6E2vErt+wK4dw+nFM0mm0q1Pc2PoAuCssybVI07jUIQ5VWGR2yXCmX5",
    "isValid": false,
    "sessionKeyASCI":"???F????6?J???w??&?J?=???\u000b????T?;?B?U?Gl?\ne?",
    "sessionKeyUTF8":"���F��?�6�J���w��&�J�=͏�\u000b��̛T�;�B�U�Gl�\ne?"
}

具体问题

  1. C#使用了哪种编码将sessionKey转换为返回结果中的字符串?我原以为是ASCII或UTF8,但实际结果与这两种编码的转换结果不同。
  2. 将sessionKey作为byte[]在POST接口中使用时能正常工作,可成功转回字符串,但我希望将该SessionKey放在请求头中传递,因此引出第三个问题。
  3. 如何将AES加密结果编码为可用于请求头的字符串,并且后续能转回byte[]?

解答

问题1:sessionKey的编码方式

返回结果中的sessionKey是Base64编码,而非ASCII或UTF8。ASP.NET Core默认序列化byte[]类型时,会自动将其转换为Base64字符串——这就是你看到的lI+ZRpzqP6E2vErt+wK4dw+...这类结果的原因。

AES加密后的字节流是二进制数据,并非合法的ASCII或UTF8字符序列,直接用文本编码转换必然会丢失数据或出现乱码,这也是你手动转换后得到乱码的原因。

问题2:POST接口传递byte[]正常的原因

POST接口中直接传递byte[]时,ASP.NET Core会自动处理二进制数据的序列化与反序列化(通常通过Base64或直接二进制传输)。但请求头的传输规则不同:请求头只能包含可打印的ASCII字符,无法直接传输二进制数据,因此需要专门的编码方案。

问题3:适配请求头的编码与解码方案

要将AES加密后的byte[]转换为可在请求头中安全传输的字符串,同时能还原为原字节数组,推荐两种方案:

方案1:标准Base64编码

标准Base64包含+、/和=字符,这些字符在请求头中可直接使用(符合HTTP规范)。编码和解码代码如下:

// 编码:byte[]转Base64字符串
string headerSafeSessionKey = Convert.ToBase64String(session.SessionKey);

// 解码:Base64字符串转回byte[]
byte[] originalBytes = Convert.FromBase64String(headerSafeSessionKey);

方案2:URL安全的Base64编码

如果担心+、/和=可能被代理或网关异常处理,可以使用URL安全的Base64变体:将+替换为-,/替换为_,并去掉末尾的=填充字符。解码时再还原为标准Base64格式:

// URL安全编码
string urlSafeBase64 = Convert.ToBase64String(session.SessionKey)
    .Replace('+', '-')
    .Replace('/', '_')
    .TrimEnd('=');

// URL安全解码
string standardBase64 = urlSafeBase64
    .Replace('-', '+')
    .Replace('_', '/');
// 补回缺失的=填充
switch (standardBase64.Length % 4)
{
    case 2: standardBase64 += "=="; break;
    case 3: standardBase64 += "="; break;
}
byte[] originalBytes = Convert.FromBase64String(standardBase64);

注意事项

  • 请求头有长度上限(通常建议不超过4KB),会话密钥类数据一般不会超出此限制;
  • 解码时必须使用与编码完全对应的规则,避免数据损坏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:36:16