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

C#解密OpenSSL AES-128-ECB加密串报错:输入数据块不完整

问题:OpenSSL可正常解密,但C#解密抛出"The input data is not a complete block"异常

一、OpenSSL解密成功的命令

使用以下OpenSSL命令可成功解密encrypted.msg文件,得到与原内容一致的明文:

openssl enc -d -aes-128-ecb -in "C:\encrypted.msg" -out "c:\temp\decrypted.msg" -K "e2fc714c4727ee9395f324cd2e7f331f" -nopad

二、C#解密异常情况

使用.NET 7的C#代码解密同一加密文件时,始终抛出异常:The input data is not a complete block。以下是原解密代码:

private static string GetHASH(byte[] RawBytes, HashAlgorithm AlgoritmoDiHASH)
{
    if (RawBytes is not { LongLength: > 0 }) return "";
    var bytes = AlgoritmoDiHASH.ComputeHash(RawBytes);
    var builder = new StringBuilder();
    foreach (var t in bytes)
    {
        builder.Append(t.ToString("x2"));
    }

    return builder.ToString();
}

public static string GetMd5(string rawData)
{
    if (string.IsNullOrEmpty(rawData))
    {
        throw new Exception();
    }

    return GetHASH(Encoding.UTF8.GetBytes(rawData), MD5.Create());
}

public static byte[] AESByteArrayDecryption(byte[] encryptedBytes, string key, CipherMode cipherMode = CipherMode.CBC, PaddingMode paddingMode = PaddingMode.PKCS7, int blockSize = 128, int keySize = 256)
{
    if (string.IsNullOrEmpty(key))
    {
        throw new Exception("Chiave di decrittazione non valida");
    }

    if (encryptedBytes.LongLength == 0)
    {
        throw new Exception("Dati da decrittografare non validi");
    }

    var keyB = new byte[32];
    var tmp = Encoding.UTF8.GetBytes(key);
    Buffer.BlockCopy(tmp, 0, keyB, 0, Math.Min(tmp.Length, 32));

    using (var rm = Aes.Create())
    {
        rm.BlockSize = blockSize;
        rm.KeySize = keySize;
        rm.Mode = cipherMode;
        rm.Padding = paddingMode;

        using (var dencryptor = rm.CreateDecryptor(keyB, (cipherMode != CipherMode.ECB ? new byte[blockSize / 8] : null)))
        {
            using (var dencryptStream = new MemoryStream(encryptedBytes))
            {
                using (var cryptoStream = new CryptoStream(dencryptStream, dencryptor, CryptoStreamMode.Read))
                {
                    var decryptBytes = new byte[encryptedBytes.Length];
                    cryptoStream.Read(decryptBytes, 0, decryptBytes.Length);
                    return decryptBytes;
                }
            }
        }
    }
}

// 调用代码
var cipherMode = CipherMode.ECB;
var paddingMode = PaddingMode.None;
var blockSize = 128;
var keySize = 256;
var pwdMD5 = CryptographyUtil.GetMd5("abcd");

var decriptedData = CryptographyUtil.AESByteArrayDecryption(criptedData, pwdMD5, cipherMode, paddingMode, blockSize, keySize);
var decriptedDataString = Encoding.UTF8.GetString(decriptedData);

注:用于生成MD5的字符串为abcd,对应的十六进制结果正是OpenSSL命令中使用的e2fc714c4727ee9395f324cd2e7f331f。

三、加密文件内容

j›}2}0‹ÂN_’-#€6µC÷úð+|™wyh”–Ú`WŽ µÄîôZÌ¢Cü‘Êœœ4zw=-á¶(ör»”qÛ‰ ÀðMl}Ï„%ðŸ9]˰ $„üÌR†E)zÆÝ‚¦”J4-¸–éÇ  æ&þ`:¯ê—ç‹ß<+K/´ö#Ë‘’Âé·_NFò‚øCUk³`Ú¾µh-ïQõ£®®èá}R±}å,M\™û‡Í°öç/–ÌàOÙ”ÒšßN¥þÀP
ø'†èì—Nh
#Ä›á•ÆöjȦJæËãJ’^_«.ÂK¯‚ýR*ËdîdtÍB¶ÆpçZÑŸ·oM°Ž7I}ŠÏáˆjS½Ð4Æ=ßÙ¿ré(»²”=[ˆÿjй„cÕ.W®ºïI±PB/úuÓŸic¸D®_¾c£3D‰Èwë‚áJì&ÛÂÙû}Cùô
—ÆÀËl¬~ЧԲÈyÇα    ÈÆhbSê¾ ç»ûg¢çð²POêA–Á“üïbV|Ë "Æ‘G&éýù>ü µr ÒÅ/Í)®8XU›M}1E2ÚÀúaâ³’d¾¦Ý»TV‘°ŠÖÀñÁa  ¤×}:*ØÎ¯ßLÿklÌÐÄàæ4úN››w—ÊÑ ù=Pzf›ÿ%J µµ¾Nf‚{eÔleÊs‹ðý…©m¤¸ò¬†0Ñü*D‰ÀøÖˆ’…RòÒ‰013¾QYó   ,&Ñ»§<»J{«»"©‡ÆÐñ,¦®â…òž~ËkAž<ꈘ]8i8ÿ0ãÚÔFÙ™ö\®ŠM—zOÓ¶·è”Y

四、明文文件内容

<reading version="2"><cam><name>Test-Road</name><serial>682719AE6F5E</serial><mac></mac></cam><date>2024-01-19T09:14:06.230Z</date><timestamp>1705655646230</timestamp><plate><adr><kemler>33</kemler><onu>1203</onu></adr><value>ABCDE123</value><direction>-1</direction><country>ITA</country><vehicle>truck</vehicle><speed>20</speed><x>1419</x><y>387</y><width>197</width><height>46</height></plate><images><ocr><url>http://localhost:7572/img/2024/01/19/10/2024-01-19-10-14-06-FG050EE_full.jpg</url></ocr><context><url>http://localhost:7572/img/2024/01/19/10/2024-01-19-10-14-06-FG050EE_ctx.jpg</url></context></images></reading>

问题根源与修正方案

1. 密钥处理错误(核心问题)

OpenSSL使用的是128位密钥(e2fc714c4727ee9395f324cd2e7f331f是32个十六进制字符,对应16字节=128位),但原C#代码存在两处错误:

  • 将MD5生成的十六进制字符串转成UTF-8字节数组,再填充到32字节数组中,这会导致密钥完全不匹配。正确做法是将十六进制字符串直接解析为字节数组。
  • 设置keySize=256,但实际使用的是AES-128,需改为keySize=128。

2. CryptoStream读取方式错误

cryptoStream.Read无法保证一次性读取所有解密后的数据,需改用循环读取或CopyTo方法获取完整数据。

3. 加密数据长度验证

当设置PaddingMode.None时,.NET要求加密数据长度必须是块大小(16字节)的整数倍。若加密文件长度不符合,需确认是否读取文件时出现截断,或加密时是否确实未添加填充。

修正后的代码

private static string GetHASH(byte[] RawBytes, HashAlgorithm AlgoritmoDiHASH)
{
    if (RawBytes is not { LongLength: > 0 }) return "";
    var bytes = AlgoritmoDiHASH.ComputeHash(RawBytes);
    var builder = new StringBuilder();
    foreach (var t in bytes)
    {
        builder.Append(t.ToString("x2"));
    }

    return builder.ToString();
}

public static string GetMd5(string rawData)
{
    if (string.IsNullOrEmpty(rawData))
    {
        throw new ArgumentException("原始数据不能为空");
    }

    return GetHASH(Encoding.UTF8.GetBytes(rawData), MD5.Create());
}

// 新增:十六进制字符串转字节数组方法
private static byte[] HexStringToByteArray(string hex)
{
    if (hex.Length % 2 != 0)
        throw new ArgumentException("十六进制字符串长度必须为偶数");
    
    byte[] bytes = new byte[hex.Length / 2];
    for (int i = 0; i < hex.Length; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }
    return bytes;
}

public static byte[] AESByteArrayDecryption(byte[] encryptedBytes, string hexKey, CipherMode cipherMode = CipherMode.CBC, PaddingMode paddingMode = PaddingMode.PKCS7, int blockSize = 128, int keySize = 128)
{
    if (string.IsNullOrEmpty(hexKey))
    {
        throw new ArgumentException("解密密钥无效");
    }

    if (encryptedBytes.LongLength == 0)
    {
        throw new ArgumentException("待解密数据无效");
    }

    // 将十六进制密钥解析为字节数组
    byte[] keyB = HexStringToByteArray(hexKey);

    using (var rm = Aes.Create())
    {
        rm.BlockSize = blockSize;
        rm.KeySize = keySize;
        rm.Mode = cipherMode;
        rm.Padding = paddingMode;
        rm.Key = keyB;
        // ECB模式不需要IV
        if (cipherMode != CipherMode.ECB)
            rm.IV = new byte[blockSize / 8];

        using (var dencryptor = rm.CreateDecryptor())
        using (var dencryptStream = new MemoryStream(encryptedBytes))
        using (var cryptoStream = new CryptoStream(dencryptStream, dencryptor, CryptoStreamMode.Read))
        using (var resultStream = new MemoryStream())
        {
            // 读取所有解密后的数据
            cryptoStream.CopyTo(resultStream);
            return resultStream.ToArray();
        }
    }
}

// 调用代码
var cipherMode = CipherMode.ECB;
var paddingMode = PaddingMode.None;
var blockSize = 128;
var keySize = 128;
var pwdMD5 = CryptographyUtil.GetMd5("abcd");

var decriptedData = CryptographyUtil.AESByteArrayDecryption(criptedData, pwdMD5, cipherMode, paddingMode, blockSize, keySize);
var decriptedDataString = Encoding.UTF8.GetString(decriptedData);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 20:45:55