【问题标题】:Why does AES decryptor always returns 16 zeros (in 16 bytes)?为什么 AES 解密器总是返回 16 个零(16 个字节)?
【发布时间】:2014-05-13 06:55:35
【问题描述】:

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

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

AA000000000000000000000000000000

以及下面的纯文本

AA000000000000000000000000000000

(同样是十六进制,是的,与密钥相同)

结果应该是

814827A94525FF24B90F20BEC065866D

确实如此。 (您可以在此处验证这应该是 http://www.cryptogrium.com/aes-encryption-online-ecb.html 的结果,并将其作为输入并选择 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)。如果您需要,我可以提供。

【问题讨论】:

  • 为什么要编写 PadRight 方法进行解密?如果他们真的在做某事,他们只能弄乱密文。
  • 我现在需要它。稍后我将使用 PKCS7,但现在我需要它们。

标签: c# encryption cryptography aes


【解决方案1】:

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

【讨论】:

  • 嗯,一个带有填充模式的块加密方法——当然正确答案,但如果你问我一个奇怪的 API。
【解决方案2】:
  1. 您正在运行的代码包括padding。填充允许不能被块大小整除的数据。在此示例中,您正在转换单个块,在这种情况下,您可以将填充模式更改为无 aes.Padding = PaddingMode.None(由 Ulugbek Umirov 回答)

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

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

鉴于您只转换一个块,最简单的做法是:

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

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

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

很抱歉回答了一个老问题,但鉴于当前接受的答案不完整,我认为提供更多详细信息会很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-07
    • 1970-01-01
    • 2015-01-11
    • 2011-09-23
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多