C# 为什么AES解密程序总是返回16个零(16字节)?

C# 为什么AES解密程序总是返回16个零(16字节)?,c#,encryption,cryptography,aes,C#,Encryption,Cryptography,Aes,我的目标是得到一个非常简单的分组密码,即 AES的核心。它必须获取一个键和一个块,然后返回一个块。解密程序应获取密钥并返回原始块 我一直在使用以下键(十六进制)进行测试 下面是纯文本 AA000000000000000000000000000000 (同样是十六进制,是,与键相同) 结果应该是 814827A94525FF24B90F20BEC065866D 确实如此。(您可以在此处验证,将此作为输入并选择AES-128,结果应为) 但解密程序总是返回 0000000000000000000

我的目标是得到一个非常简单的分组密码,即 AES的核心。它必须获取一个键和一个块,然后返回一个块。解密程序应获取密钥并返回原始块

我一直在使用以下键(十六进制)进行测试

下面是纯文本

AA000000000000000000000000000000
(同样是十六进制,是,与键相同)

结果应该是

814827A94525FF24B90F20BEC065866D
确实如此。(您可以在此处验证,将此作为输入并选择AES-128,结果应为)

但解密程序总是返回

00000000000000000000000000000000
(只有零)

在下面的实现中我做错了什么?此实施仅用于教育目的。这就是我使用ECB模式的原因,也是我希望始终使用相同的加密方式的原因

namespace CryptographyCSharp
{
using System;
using System.Security.Cryptography;

public class MyAes
{
    public static string EncryptStringToBytes_Aes(string msg_hex, string key_hex)
    {
        if (msg_hex == null)
            throw new ArgumentNullException("msg_hex");
        if (key_hex == null)
            throw new ArgumentNullException("key_hex");

        byte[] output = new byte[16];
        msg_hex = msg_hex.PadRight(32, '0');
        key_hex = key_hex.PadRight(32, '0');
        using (var aes = Aes.Create("AES"))
        {
            
            aes.BlockSize = 128;
            aes.KeySize = 128;
            aes.Mode = CipherMode.ECB;
            if (!aes.ValidKeySize(128))
            {
                throw new Exception();
            }

            ICryptoTransform encryptor = aes.CreateEncryptor(key_hex.hex2bytes(), null);
            encryptor.TransformBlock(msg_hex.hex2bytes(), 0, 16, output, 0);
            encryptor.Dispose();
        }

        return output.tohex();
    }

    public static string DecryptStringFromBytes_Aes(string hex_ct, string key_hex)
    {
        if (hex_ct == null)
            throw new ArgumentNullException("cipherText");
        if (key_hex == null)
            throw new ArgumentNullException("Key");

        hex_ct = hex_ct.PadRight(32, '0');
        key_hex = key_hex.PadRight(32, '0');
        string plaintext = null;

        using (Aes aes = Aes.Create("AES"))
        {
            aes.BlockSize = 128;
            aes.KeySize = 128;
            aes.Mode = CipherMode.ECB;
            if (!aes.ValidKeySize(128))
            {
                throw new Exception();
            }

            ICryptoTransform decryptor = aes.CreateDecryptor(key_hex.hex2bytes(), null);
            var output = new byte[16];
            decryptor.TransformBlock(hex_ct.hex2bytes(), 0, 16, output, 0);
            plaintext = output.tohex();
        }

        return plaintext;
    }
}
}

我使用了一些扩展方法,将十六进制转换为字节,反之亦然(即string.hex2bytes和bytes[].tohex)。如果您需要,我可以提供。

添加
aes.Padding=PaddingMode.None

  • 您正在运行的代码包括。填充允许数据不能被块大小均匀整除。在本例中,您正在转换单个块,在这种情况下,您可以将填充模式更改为none
    aes.padding=PaddingMode.none
    (由Ulugbek Umirov回答)

  • ICryptoTransform.TransformBlock()
    函数返回写入输出的字节数,该字节数可以小于必须适应这种情况的块大小

  • encryptor.TransformFinalBlock()
    函数应始终最后调用,这可能包括额外的字节。可以使用空字节数组作为输入来调用它

  • 鉴于您仅转换单个块,最简单的方法是:

  • 添加
    aes.Padding=PaddingMode.None
  • 更改以下行
    encryptor.TransformBlock(msg_hex.hex2bytes(),0,16,输出,0)

    output=encryptor.TransformFinalBlock(msg_hex.hex2bytes(),0,16)


  • 很抱歉回答了一个老问题,但鉴于当前接受的答案不完整,我认为提供额外的细节会很有用。

    为什么要编写正确的解密方法?如果他们真的在做什么,他们只能把密文弄乱。我现在就需要这样。稍后我将使用PKCS7,但现在我需要它们。嗯,一个带有填充模式的块加密方法-当然正确答案,但是如果你问我的话,它是一个奇怪的API。
    namespace CryptographyCSharp
    {
    using System;
    using System.Security.Cryptography;
    
    public class MyAes
    {
        public static string EncryptStringToBytes_Aes(string msg_hex, string key_hex)
        {
            if (msg_hex == null)
                throw new ArgumentNullException("msg_hex");
            if (key_hex == null)
                throw new ArgumentNullException("key_hex");
    
            byte[] output = new byte[16];
            msg_hex = msg_hex.PadRight(32, '0');
            key_hex = key_hex.PadRight(32, '0');
            using (var aes = Aes.Create("AES"))
            {
                
                aes.BlockSize = 128;
                aes.KeySize = 128;
                aes.Mode = CipherMode.ECB;
                if (!aes.ValidKeySize(128))
                {
                    throw new Exception();
                }
    
                ICryptoTransform encryptor = aes.CreateEncryptor(key_hex.hex2bytes(), null);
                encryptor.TransformBlock(msg_hex.hex2bytes(), 0, 16, output, 0);
                encryptor.Dispose();
            }
    
            return output.tohex();
        }
    
        public static string DecryptStringFromBytes_Aes(string hex_ct, string key_hex)
        {
            if (hex_ct == null)
                throw new ArgumentNullException("cipherText");
            if (key_hex == null)
                throw new ArgumentNullException("Key");
    
            hex_ct = hex_ct.PadRight(32, '0');
            key_hex = key_hex.PadRight(32, '0');
            string plaintext = null;
    
            using (Aes aes = Aes.Create("AES"))
            {
                aes.BlockSize = 128;
                aes.KeySize = 128;
                aes.Mode = CipherMode.ECB;
                if (!aes.ValidKeySize(128))
                {
                    throw new Exception();
                }
    
                ICryptoTransform decryptor = aes.CreateDecryptor(key_hex.hex2bytes(), null);
                var output = new byte[16];
                decryptor.TransformBlock(hex_ct.hex2bytes(), 0, 16, output, 0);
                plaintext = output.tohex();
            }
    
            return plaintext;
        }
    }
    }