2016-02-11 3 views
1

Я получаю сказал ошибка при попытке реализовать шифрование и дешифрование DES (Хотя мой код позволяет для различных реализаций)C# Bad PKCS7 Перетяжка

Я сделал много исследований по этому вопросу и обнаружил несколько подобных вопросы, здесь, в разделе «Переполнение стека», однако ответ, который они предоставляют, заключается в том, чтобы гарантировать, что ключ и IV идентичны в процессе шифрования и дешифрования, я, похоже, уже реализовал это, поэтому кажется, что корень проблемы лежит где-то в другом месте.

Ниже мой код, то исключение на линии № 164

namespace xNFCE 
{ 
    public class Crypto 
    { 

     public enum cryptype 
     { 
      DES, 
      THREEDES, 
      AES 
     }; 

     // Variables for the file input, output and the password to encrypt the file 
     string _input, _output; 
     byte[] _password; 
     cryptype _type; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="xNFCE.Crypto"/> class. 
     /// </summary> 
     /// <param name="input">Input.</param> 
     /// <param name="output">Output.</param> 
     /// <param name="password">Password.</param> 
     public Crypto(string input, string output, string password, cryptype type = cryptype.AES) 
     { 
      // Set the properties for the encryption 
      _input = input; 
      _output = output; 
      _password = hash(password); 
      _type = type; 
     } 


     /// <summary> 
     /// Run the appropriate encryption function 
     /// </summary> 
     public void Encrypt() 
     { 
      switch (_type) 
      { 
       case cryptype.DES: 
        DESenc(); 
        break; 
       case cryptype.THREEDES: 
        // TODO Implement 
        throw new NotImplementedException(); 
       case cryptype.AES: 
        // TODO Implement 
        throw new NotImplementedException(); 
      } 
     } 


     /// <summary> 
     /// Run the appropriate decryption function 
     /// </summary> 
     public void Decrypt() 
     { 
      switch (_type) 
      { 
       case cryptype.DES: 
        DESdec(); 
        break; 
       case cryptype.THREEDES: 
        // TODO Implement 
        throw new NotImplementedException(); 
       case cryptype.AES: 
        // TODO Implement 
        throw new NotImplementedException(); 
      } 
     } 


     /// <summary> 
     /// Hash the password and return it as a byte array 
     /// </summary> 
     /// <param name="pwd">Pwd.</param> 
     byte[] hash(String pwd) 
     { 
      // System.Text provides .GetBytes() this converts a string to the series of bytes 
      // Convert the password string to an array of bytes 
      byte[] bytes = Encoding.ASCII.GetBytes(pwd); 
      // Create an instance of Managed SHA256 
      SHA256Managed hashman = new SHA256Managed(); 
      // Hash the array of bytes 
      byte[] hash = hashman.ComputeHash(bytes); 
      return hash; 
     } 

     /// <summary> 
     /// This function is called when the user wants to encrypt a file 
     /// </summary> 
     void DESenc() 
     { 
      // Create file streams for the input and output of the files 
      FileStream fileInput = new FileStream(_input, FileMode.Open, FileAccess.Read); 
      // Append the xNFCE extension to the output 
      FileStream fileEncrypted = new FileStream(_output + GlobalValues.fextension, FileMode.Create, FileAccess.Write); 

      // Declare an insrance of the DESCryptoServiceProvider class 
      // This represents the actual encryption and decryption technology that is used on the files 
      // Other cryptographic techniques can be used here 
      // TODO implement other encryption techniques 
      DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 

      // Each cryptographic technique takes a different syze key, DES takes a 64Bit key which is 8 Bytes (8 Characters) 
      // If we do not provide a key and IV here, they are randomly generated, meaning we cannot decrypt the file 
      // Take the first 8 bytes from the password 
      DES.Key = _password.Take(8).ToArray(); 
      DES.IV = _password.Take(8).ToArray(); 

      // Cretae an instance of the CryptoStream class by using the cryptographic prover to obtain an encrypting object 
      // and the existing output filestream as part of the constructor. 
      ICryptoTransform desencrypt = DES.CreateEncryptor(); 
      CryptoStream cryptostream = new CryptoStream(fileEncrypted, desencrypt, CryptoStreamMode.Write); 

      // Read in the input file and write to the output file while passing through the crypto stream object using the password provided 
      byte[] bytearrayinput = new byte[fileInput.Length - 1]; 
      fileInput.Read(bytearrayinput, 0, bytearrayinput.Length); 
      cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length); 
     } 


     /// <summary> 
     /// This function is called when the user wants to decrypt a file 
     /// </summary> 
     void DESdec() 
     { 
      // This function has two key differences from the encrypt function 
      // CreateDecryptor is used instead of CreateEncryptor to create the crypto stream object 
      // When the decrypted text is written to the destination file, the CryptoStream object is now the source isntead of the destination stream 
      DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 
      // Take the first 8 bytes from the password 
      DES.Key = _password.Take(8).ToArray(); 
      DES.IV = _password.Take(8).ToArray(); 

      // Create the file stream to read the encrypted file back 
      FileStream fileInput = new FileStream(_input, FileMode.Open, FileAccess.Read); 
      // Create a DES decryptor 
      ICryptoTransform desdecrypt = DES.CreateDecryptor(); 
      // Create a crypto stream set to read and do a decryption transform on incoming bytes 
      CryptoStream cryptostream = new CryptoStream(fileInput, desdecrypt, CryptoStreamMode.Read); 

      // Print the contents of the decrypted file 
      FileInfo fi = new FileInfo(_output); 
      string writename = Path.Combine(fi.DirectoryName, Path.GetFileNameWithoutExtension(_output)); 
      StreamWriter fsDecrypted = new StreamWriter(writename); 
      fsDecrypted.Write(new StreamReader(cryptostream).ReadToEnd()); 
      fsDecrypted.Flush(); 
      fsDecrypted.Close(); 
     } 

    } 
} 

Примечание: Я использую Xamarin.Android для этого, но я не верю, что это отношение

Спасибо! :)

+2

Не использовать DES, это небезопасно, даже 3DES не следует использовать в новой работе, использовать AES. Также никогда не используйте одно и то же значение для ключа и iv, iv не обязательно должен быть секретным, а вообще нет, ключ должен быть секретным. Это проблема с «большим количеством исследований в Интернете, существует много плохой информации, вам нужно знать, что источник информации известен». – zaph

ответ

2

Проблема заключается в том, что зашифрованный файл будет пустым, поэтому впоследствии вы попытаетесь расшифровать пустую строку, которая завершится с ошибкой.

Файл пуст, потому что CryptoStream никогда не сбрасывается на диск.

Это связано с тем, что вы не утилизацией ничего, что вам нужно, чтобы вернуться и добавить пункт using() {} к чему-либо, реализующего IDisposable (делает это для CryptoStream сбросит его правильно).

В минимальной:

using (CryptoStream cryptostream = new CryptoStream(fileEncrypted, desencrypt, CryptoStreamMode.Write)) 
{ 
    // Read in the input file and write to the output file while passing through the crypto stream object using the password provided 
    byte[] bytearrayinput = new byte[fileInput.Length - 1]; 
    fileInput.Read(bytearrayinput, 0, bytearrayinput.Length); 

    cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length); 
} 

бы заставить вашу программу вести себя, как ожидалось. (но все же утечка в другом месте).

(Не используйте одинаковые значения для ключа и IV)

+0

Спасибо! Это остановило исключение из-за того, что оно было выброшено, хотя выходной файл кажется в два раза больше размера входного файла и нечитабельно. Однако сомневаюсь, что это связано с этой проблемой. Еще раз спасибо! – JLangford

+0

Редактировать: Какая альтернатива для того, чтобы не использовать одно и то же значение для ключа и iv? Я только хочу, чтобы пользователь нужно ввести одну кодовую фразу, следует ли взять другую часть хэша? – JLangford

Смежные вопросы