【问题标题】:C# AES-128 CFB Error [duplicate]C# AES-128 CFB 错误 [重复]
【发布时间】:2015-03-14 02:09:04
【问题描述】:

我目前以这种方式设置 RijndaelManaged(由于服务器处理加密的方式,IV 和密钥相同)。服务器也使用CFB8作为模式,我设置对了吗?

    public static RijndaelManaged GenerateAES(byte[] key)
    {
        RijndaelManaged cipher = new RijndaelManaged();
        cipher.Mode = CipherMode.CFB;
        cipher.Padding = PaddingMode.None;
        cipher.KeySize = 128;
        cipher.Key = key;
        cipher.IV = key;

        return cipher;
    }

我这样写数据: ICryptoTransform e = GenerateAES(key).CreateEncryptor();

        using(CryptoStream stream = new CryptoStream(BaseStream, e, CryptoStreamMode.Write))
        {
            stream.WriteByte(b);
            stream.FlushFinalBlock();
        }

BaseStream 是我打开的 NetworkStream,'b' 是我发送给我的函数的值。

当我尝试对流进行 0x00(作为测试)时,我收到此错误:

System.Security.Cryptography.CryptographicException: Length of the data to encrypt is invalid.
at System.Security.Cryptography.RijndaelManagedTransform.EncryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()

我只是让这个函数测试我是否可以在不依赖任何外部库的情况下与服务器通信。

【问题讨论】:

    标签: c# aes


    【解决方案1】:

    您已将PaddingMode 设置为无,并且尝试加密的字节数少于完整的数据块。要么加密更多数据(cipher.BlockSize 的倍数),要么将填充模式设置为 None 以外的其他值,以便自动填充到适当的长度。

    编辑:

    RijndaelManaged 的​​默认 FeedbackSize 为 128 位,但您想使用 CFB8。如果您将cipher.FeedbackSize 设置为 8,您将能够将其用作没有填充的流密码,并且写入 CryptoStream 的每个字节都将被加密并立即写入输出流。您应该在每次写入后调用FlushFinalBlock,因为这会终止加密过程。

    【讨论】:

    • 没有填充,我很确定。出于绝望,我尝试将 PaddingMode 更改为零,它似乎工作,直到我收到写入错误(流突然变得无法写入)。
    • @SwDevMan81 不,在加密之前对明文应用填充以允许分组密码(如 AES)对任何长度的明文进行操作。来自 MSDN 上的 PaddingMode 枚举:“大多数纯文本消息不包含完全填充块的字节数。通常,没有足够的字节来填充最后一个块。发生这种情况时,会在文本中添加一个填充字符串。”
    • @0xFF 如果服务器不使用填充,那么您要加密的数据必须的长度等于块大小的倍数,这就是块密码的工作原理.
    • +1 听起来不错 - 只需将您的测试数据更改为 128 位(默认块大小)就可以了。
    • 问题是我随时都需要写一个字节或者字节数组(任意长度的数组),以后怎样才能避免这样的问题呢?
    【解决方案2】:

    这里提供了一个解决方案: https://stackoverflow.com/a/29038974/725903

    这个想法是包装 ICryptoTransform 传递给处理 TransformFinalBlock 的 CryptoStream ctor,在加密/解密之前添加所需的字节并在返回时删除它们

    【讨论】:

      猜你喜欢
      • 2019-02-15
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多