【问题标题】:C# aes encryption: Input size not output sizeC# aes 加密:输入大小而不是输出大小
【发布时间】:2015-03-14 02:19:00
【问题描述】:

我正在尝试读取文件,对其进行加密,然后通过套接字将其发送到服务器,并在那里写入。然后反过来,在服务器上读取,发送给客户端,解密,再写入。

我使用 C# Aes 类的问题是,输入大小不等于输出大小。

例如,当我从文件中读取 4096 字节时,输出大小为 4112 字节,多出 16 字节。好的,所以在服务器上发送和写入了 4112 个字节,但是当我再次获取文件时,我只能通过套接字发送最多 4096 个字节,然后,当然,客户端上的解密函数会抛出异常,即填充无效,无法删除。当然,我可以尝试在客户端读取更少的字节,但这也不起作用。

我是一位非常有经验的 C++ 程序员,我已经使用 OpenSsl 完成了这项工作,它的工作原理非常棒。输入大小一直是输出大小,我不知道我在 C# 中的函数有什么问题。

这是发送部分:

byte[]  SendData = new byte[4096];

iBytesRead = FileRead.Read (SendData, 0, 4096);

SendData = aes.encrypt (Encoding.Default.GetString (SendData, 0, iBytesRead), iBytesRead);

String a = aes.decrypt (SendData); // no problems here because the size is correct

Socket.sendB     (SendData, SendData.Length);

以及从服务器接收的部分:

byte[] WriteData = new byte[4096],
                   Temp;

if ((iBytesReceived = Socket.receiveB (ref WriteData)) == 0)
    break;

if (Encoding.ASCII.GetString (WriteData, 0, iBytesReceived) == "end")
    break;


for (uint i = 0; i < iBytesReceived; i++)
    Temp[i] = WriteData[i];

byte[] a = Encoding.Default.GetBytes (aes.decrypt (Temp));

FileWrite.Write (a, 0, Temp.Length);

Aes 函数:

public byte[] encrypt(String _InStr, int _InStrLength)
    {
        if (!bKeySet)
            return ErrorReturn;

        byte[] encrypted;

        using (Aes aes = Aes.Create ())
        {
            aes.Key = Key;
            aes.IV = IV;

            //aes.Padding = PaddingMode.PKCS7;
            //aes.BlockSize = 128;
            //aes.KeySize = 128;
            //aes.Mode = CipherMode.CFB;

            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

            // Create the streams used for encryption. 
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter sw = new StreamWriter(cs))
                    {
                        sw.Write(_InStr);                   
                    }
                }

                ms.Close ();

                encrypted = ms.ToArray (); 
            }
        }

        return encrypted;
    }

    public String decrypt(byte[] _InStr)
    {
        if (!bKeySet)
            return "";

        String plaintext;


        using (Aes aes = Aes.Create ())
        {
            aes.Key = Key;
            aes.IV = IV;

            //aes.Padding = PaddingMode.PKCS7;
            //aes.BlockSize = 128;
            //aes.KeySize = 128;
            //aes.Mode = CipherMode.CBC;

            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

            // Create the streams used for decryption. 
            using (MemoryStream msDecrypt = new MemoryStream(_InStr))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        plaintext = srDecrypt.ReadToEnd ();
                    }
                }
            }
        }

        return plaintext;
    }

【问题讨论】:

  • 使用 NoPadding 时,输入大小只能等于输出大小。 PKCS7Padding 总是产生 1-16 个额外字节(对于 AES)来填充到 16 的倍数。因此您可能会尝试读取 4095 字节而不是 4096。目前尚不清楚为什么不能使用较小的缓冲区。
  • @ArtjomB。然后我在加密函数中得到这个:The input data is not a complete block

标签: c# sockets encryption aes


【解决方案1】:

如前所述,如果使用任何填充,输出将与块大小对齐。但是,当使用 PaddingMode.None 时,.Net 不想使用不完整的块。您应该在加密(解密)之前自己填充数据并在之后删除添加的字节。 一种方法是将wrap ICryptoTransform 传递给 CryptoStream

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 2013-02-26
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多