2015-02-08 3 views
0

Я пытаюсь прочитать файл, зашифровать его и отправить его на сервер через сокет, где он написан. А потом наоборот, прочитайте его на сервере, отправьте его клиенту, расшифруйте его и запишите снова.C# aes encryption: Размер входного файла не равен размеру

Моя проблема с использованием класса C# Aes заключается в том, что размер ввода не равен размеру вывода.

Например, когда я прочитал 4096 байт из файла, размер вывода составляет 4112 байт, еще 16 байт. ОК, поэтому 4112 байт отправляются и записываются на сервер, но когда я снова получаю файл, я могу отправлять только 4096 байт по сокету, а затем, конечно, функция расшифровки на клиенте выдает исключение, которое отступ недействителен и не может быть удален. Конечно, я мог бы попытаться читать меньше байтов на клиенте, но это не работает.

Я очень опытный программист на С ++, и я сделал это с 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); 

äes функции:

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; 
    } 
+0

Размер ввода может равняться только размеру выхода при использовании NoPadding. PKCS7Padding всегда производит 1-16 дополнительных байтов (для AES), чтобы заполнить до кратного 16. Таким образом, вы можете попробовать прочитать 4095 байт вместо 4096. Неясно, почему вы не можете использовать меньший буфер. –

+0

@ArtjomB. Затем я получаю это в функции шифрования: «Входные данные не являются полным блоком» – schacker22

ответ

0

Как уже было сказано, если обивка , выход будет выровнен с размером блока. Однако .Net не хочет работать с неполными блоками при использовании PaddingMode.None. Прежде чем шифровать (дешифровать), вы должны прокладывать данные самостоятельно и удалять добавленные байты. Один из способов сделать это - wrap ICryptoTransform, переданный CryptoStream