为什么AES解密器总是返回16个零(16个字节)?

时间:2014-05-13 06:55:35

标签: c# encryption cryptography aes

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

我一直在使用以下密钥进行测试

AA000000000000000000000000000000

(十六进制)

以及以下纯文本

AA000000000000000000000000000000

(再次以十六进制表示,是的,与键相同)

结果应为:

814827A94525FF24B90F20BEC065866D
事实确实如此。 (您可以在此验证结果应该是:http://seit.unsw.adfa.edu.au/staff/sites/lpb/src/AEScalc/AEScalc.html它使用的是Java小程序。)

但是解密器总是返回

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)。如果你需要,我可以提供。

2 个答案:

答案 0 :(得分:4)

在解密方法中添加aes.Padding = PaddingMode.None;

答案 1 :(得分:1)

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

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

  3. 应始终最后调用encryptor.TransformFinalBlock()函数,这可能包含其他字节。可以使用空字节数组作为输入来调用它。

  4. 鉴于您只是在转换单个块,最简单的方法是:

    1. 添加aes.Padding = PaddingMode.None
    2. 更改以下行
        

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

    3. 对于回答旧问题的道歉,但鉴于当前接受的答案不完整,我认为提供其他详细信息会很有用。