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

Python与C#中AES加解密结果不一致问题排查

问题描述

在Linux(Debian、Ubuntu)系统中使用Python3的pycryptodome包实现AES加解密,现需在Windows系统用C#实现同款程序,但跨语言加解密结果存在不一致问题:

  • Python加密内容在C#解密时因填充错误抛出异常;
  • C#加密内容有时无法在Python解密;
  • 同语言内加密解密可正常完成。

已验证Windows上的Python程序与Linux表现一致,但必须使用C#实现。

测试示例:

  • Python:t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68j' -> d:'TEST+++TEST+++TEST'
  • C#:t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68jdQ==' -> d:'TEST+++TEST+++TEST'

Python实现代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import base64

# pip install pycryptodome
from Crypto.Cipher import AES

KEY   = b'\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41'
IV    = b'\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41'
MODE  = AES.MODE_CFB
BLOCK = 128

def en(plain_text):
    crypto = AES.new(key=KEY, mode=MODE, iv=IV)
    crypto.block_size = BLOCK
    b_plain = plain_text.encode('utf-8')
    b_encrypted = crypto.encrypt(b_plain)
    base64_encrypted_text = base64.b64encode(b_encrypted).decode('utf-8')
    return base64_encrypted_text

def de(base64_encrypted_text):
    crypto = AES.new(key=KEY, mode=MODE, iv=IV)
    crypto.block_size = BLOCK
    b_encrypted = base64.b64decode(base64_encrypted_text)
    b_plain = crypto.decrypt(b_encrypted)
    plain_text = b_plain.decode('utf-8')
    return plain_text

t = 'TEST+++TEST+++TEST'
e = en(t)
d = de(e)
print(f"t:'{t}' -> e:'{e}' -> d:'{d}'")
# t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68j' -> d:'TEST+++TEST+++TEST'

C#实现代码

// C# .NET 6.0 Console
//

using System.Security.Cryptography;

byte[] KEY = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
byte[] IV = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
CipherMode MODE = CipherMode.CFB;
int BLOCK = 128;

string en(string plain_text)
{
    string base64_encrypted_text;
    using (var crypto = Aes.Create())
    {
        crypto.Mode = MODE;
        crypto.BlockSize = BLOCK;
        crypto.Key = KEY;
        crypto.IV = IV;
        using (var s_encrypted = new MemoryStream())
        {
            using (var s_crypto = new CryptoStream(s_encrypted, crypto.CreateEncryptor(KEY, IV), CryptoStreamMode.Write))
            {
                using (var s_plain = new StreamWriter(s_crypto))
                {
                    s_plain.Write(plain_text);
                }
            }
            base64_encrypted_text = Convert.ToBase64String(s_encrypted.ToArray());
        }
    }
    return base64_encrypted_text;
}

string de(string base64_encrypted_text)
{
    string plain_text;
    using (var crypto = Aes.Create())
    {
        crypto.Mode = MODE;
        crypto.BlockSize = BLOCK;
        crypto.Key = KEY;
        crypto.IV = IV;
        var b_encrypted = Convert.FromBase64String(base64_encrypted_text);
        using (var s_encrypted = new MemoryStream(b_encrypted))
        {
            using (var s_crypto = new CryptoStream(s_encrypted, crypto.CreateDecryptor(KEY, IV), CryptoStreamMode.Read))
            {
                using (var s_plain = new StreamReader(s_crypto))
                {
                    plain_text = s_plain.ReadToEnd();
                }
            }
        }
    }
    return plain_text;
}

var t = "TEST+++TEST+++TEST";
var e = en(t);
var d = de(e);
Console.WriteLine($"t:'{t}' -> e:'{e}' -> d:'{d}'");
// t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68jdQ==' -> d:'TEST+++TEST+++TEST'
问题原因与解决方案

核心差异点

  1. CFB模式反馈位长度不匹配
    PyCryptodome的AES-CFB默认使用8位反馈长度(CFB8),而.NET的Aes类默认使用128位反馈长度(CFB128),这是加密结果长度、内容不一致的根本原因。

  2. 填充机制误触发
    CFB属于流加密模式,本身不需要填充,但.NET的CryptoStream因反馈长度不匹配,会在解密时误判需要填充,进而抛出填充错误异常。

修正方案

C#代码修改要点

  • 指定FeedbackSize = 8,与Python端保持一致的CFB反馈长度;
  • 设置Padding = PaddingMode.None,明确流模式不需要填充;
  • 直接操作字节数组替代StreamWriter/StreamReader,避免编码转换潜在问题。

修正后的C#代码

// C# .NET 6.0 Console
using System.Security.Cryptography;

byte[] KEY = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
byte[] IV = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
CipherMode MODE = CipherMode.CFB;
int BLOCK = 128;
int FEEDBACK_SIZE = 8; // 和Python端对齐的CFB反馈长度

string en(string plain_text)
{
    byte[] plainBytes = System.Text.Encoding.UTF8.GetBytes(plain_text);
    using (var crypto = Aes.Create())
    {
        crypto.Mode = MODE;
        crypto.BlockSize = BLOCK;
        crypto.Key = KEY;
        crypto.IV = IV;
        crypto.FeedbackSize = FEEDBACK_SIZE;
        crypto.Padding = PaddingMode.None;

        byte[] encryptedBytes = crypto.CreateEncryptor().TransformFinalBlock(plainBytes, 0, plainBytes.Length);
        return Convert.ToBase64String(encryptedBytes);
    }
}

string de(string base64_encrypted_text)
{
    byte[] encryptedBytes = Convert.FromBase64String(base64_encrypted_text);
    using (var crypto = Aes.Create())
    {
        crypto.Mode = MODE;
        crypto.BlockSize = BLOCK;
        crypto.Key = KEY;
        crypto.IV = IV;
        crypto.FeedbackSize = FEEDBACK_SIZE;
        crypto.Padding = PaddingMode.None;

        byte[] plainBytes = crypto.CreateDecryptor().TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
        return System.Text.Encoding.UTF8.GetString(plainBytes);
    }
}

var t = "TEST+++TEST+++TEST";
var e = en(t);
var d = de(e);
Console.WriteLine($"t:'{t}' -> e:'{e}' -> d:'{d}'");
// 输出将与Python完全一致:t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68j' -> d:'TEST+++TEST+++TEST'

验证结果

修改后,C#与Python的加密结果完全一致,跨语言加解密可正常互操作:

  • Python加密内容能在C#正常解密;
  • C#加密内容能在Python正常解密;
  • 填充错误异常不再出现。

内容的提问来源于stack exchange,提问作者beta-tester

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:55:16