2010-01-05 9 views
2

Я в процессе перезаписи старого приложения. Старое приложение хранило данные в файле табло, который был зашифрован следующим кодом:.NET-файл Расшифровка - Плохие данные

private const String SSecretKey = @"?B?n?Mj?"; 
public DataTable GetScoreboardFromFile() 
{ 
    FileInfo f = new FileInfo(scoreBoardLocation); 
    if (!f.Exists) 
    { 
     return setupNewScoreBoard(); 
    } 

    DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 
    //A 64 bit key and IV is required for this provider. 
    //Set secret key For DES algorithm. 
    DES.Key = ASCIIEncoding.ASCII.GetBytes(SSecretKey); 
    //Set initialization vector. 
    DES.IV = ASCIIEncoding.ASCII.GetBytes(SSecretKey); 

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

    DataTable dTable = new DataTable("scoreboard"); 
    dTable.ReadXml(new StreamReader(cryptostreamDecr)); 

    cryptostreamDecr.Close(); 
    fsread.Close(); 

    return dTable; 
} 

Это прекрасно работает. Я скопировал код в свое новое приложение, чтобы создать устаревший загрузчик и преобразовать данные в новый формат. Проблема в том, я получаю сообщение об ошибке "Bad Data":

System.Security.Cryptography.CryptographicException было необработанное сообщение = "Bad Data \ г \ п." Source = "mscorlib"

Пожары ошибок в этой строке:

dTable.ReadXml(new StreamReader(cryptostreamDecr)); 

Зашифрованный файл был создан сегодня на той же машине со старым кодом. Я предполагаю, что, возможно, процесс шифрования/дешифрования использует имя/файл приложения или что-то еще, а значит, я не могу его открыть.

Кто-нибудь есть идея, как к:

A) Уметь объяснить, почему это не работает? B) Предложите решение, которое позволит мне открывать файлы, созданные с помощью устаревшего приложения, и иметь возможность их конвертировать?

Вот весь класс, который имеет дело с загрузки и сохранения табло:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Security.Cryptography; 
using System.Runtime.InteropServices; 
using System.IO; 
using System.Data; 
using System.Xml; 
using System.Threading; 

namespace JawBreaker 
{ 
[Serializable] 
class ScoreBoardLoader 
{ 
    private Jawbreaker jawbreaker; 
    private String sSecretKey = @"?B?n?Mj?"; 
    private String scoreBoardFileLocation = ""; 
    private bool keepScoreBoardUpdated = true; 
    private int intTimer = 180000; 

    public ScoreBoardLoader(Jawbreaker jawbreaker, String scoreBoardFileLocation) 
    { 
     this.jawbreaker = jawbreaker; 
     this.scoreBoardFileLocation = scoreBoardFileLocation; 
    } 

    // Call this function to remove the key from memory after use for security 
    [System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory")] 
    public static extern bool ZeroMemory(IntPtr Destination, int Length); 

    // Function to Generate a 64 bits Key. 
    private string GenerateKey() 
    { 
     // Create an instance of Symetric Algorithm. Key and IV is generated automatically. 
     DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create(); 

     // Use the Automatically generated key for Encryption. 
     return ASCIIEncoding.ASCII.GetString(desCrypto.Key); 
    } 

    public void writeScoreboardToFile() 
    { 
     DataTable tempScoreBoard = getScoreboardFromFile(); 
     //add in the new scores to the end of the file. 
     for (int i = 0; i < jawbreaker.Scoreboard.Rows.Count; i++) 
     { 
      DataRow row = tempScoreBoard.NewRow(); 
      row.ItemArray = jawbreaker.Scoreboard.Rows[i].ItemArray; 
      tempScoreBoard.Rows.Add(row); 
     } 

     //before it is written back to the file make sure we update the sync info 
     if (jawbreaker.SyncScoreboard) 
     { 
      //connect to webservice, login and update all the scores that have not been synced. 

      for (int i = 0; i < tempScoreBoard.Rows.Count; i++) 
      { 
       try 
       { 
        //check to see if that row has been synced to the server 
        if (!Boolean.Parse(tempScoreBoard.Rows[i].ItemArray[7].ToString())) 
        { 
         //sync info to server 

         //update the row to say that it has been updated 
         object[] tempArray = tempScoreBoard.Rows[i].ItemArray; 
         tempArray[7] = true; 
         tempScoreBoard.Rows[i].ItemArray = tempArray; 
         tempScoreBoard.AcceptChanges(); 
        } 
       } 
       catch (Exception ex) 
       { 
        jawbreaker.writeErrorToLog("ERROR OCCURED DURING SYNC TO SERVER UPDATE: " + ex.Message); 
       } 
      } 
     } 

     FileStream fsEncrypted = new FileStream(scoreBoardFileLocation, FileMode.Create, FileAccess.Write); 
     DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 
     DES.Key = ASCIIEncoding.ASCII.GetBytes(sSecretKey); 
     DES.IV = ASCIIEncoding.ASCII.GetBytes(sSecretKey); 
     ICryptoTransform desencrypt = DES.CreateEncryptor(); 
     CryptoStream cryptostream = new CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write); 

     MemoryStream ms = new MemoryStream(); 
     tempScoreBoard.WriteXml(ms, XmlWriteMode.WriteSchema); 

     ms.Position = 0; 

     byte[] bitarray = new byte[ms.Length]; 
     ms.Read(bitarray, 0, bitarray.Length); 

     cryptostream.Write(bitarray, 0, bitarray.Length); 
     cryptostream.Close(); 
     ms.Close(); 

     //now the scores have been added to the file remove them from the datatable 
     jawbreaker.Scoreboard.Rows.Clear(); 
    } 

    public void startPeriodicScoreboardWriteToFile() 
    { 
     while (keepScoreBoardUpdated) 
     { 
      //three minute sleep. 
      Thread.Sleep(intTimer); 
      writeScoreboardToFile(); 
     } 
    } 

    public void stopPeriodicScoreboardWriteToFile() 
    { 
     keepScoreBoardUpdated = false; 
    } 

    public int IntTimer 
    { 
     get 
     { 
      return intTimer; 
     } 
     set 
     { 
      intTimer = value; 
     } 
    } 

    public DataTable getScoreboardFromFile() 
    { 
     FileInfo f = new FileInfo(scoreBoardFileLocation); 
     if (!f.Exists) 
     { 
      jawbreaker.writeInfoToLog("Scoreboard not there so creating new one"); 
      return setupNewScoreBoard(); 
     } 
     else 
     { 
      DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 
      //A 64 bit key and IV is required for this provider. 
      //Set secret key For DES algorithm. 
      DES.Key = ASCIIEncoding.ASCII.GetBytes(sSecretKey); 
      //Set initialization vector. 
      DES.IV = ASCIIEncoding.ASCII.GetBytes(sSecretKey); 

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

      DataTable dTable = new DataTable("scoreboard"); 
      dTable.ReadXml(new StreamReader(cryptostreamDecr)); 

      cryptostreamDecr.Close(); 
      fsread.Close(); 

      return dTable; 
     } 
    } 

    public DataTable setupNewScoreBoard() 
    { 
     //scoreboard info into dataset 
     DataTable scoreboard = new DataTable("scoreboard"); 
     scoreboard.Columns.Add(new DataColumn("playername", System.Type.GetType("System.String"))); 
     scoreboard.Columns.Add(new DataColumn("score", System.Type.GetType("System.Int32"))); 
     scoreboard.Columns.Add(new DataColumn("ballnumber", System.Type.GetType("System.Int32"))); 
     scoreboard.Columns.Add(new DataColumn("xsize", System.Type.GetType("System.Int32"))); 
     scoreboard.Columns.Add(new DataColumn("ysize", System.Type.GetType("System.Int32"))); 
     scoreboard.Columns.Add(new DataColumn("gametype", System.Type.GetType("System.String"))); 
     scoreboard.Columns.Add(new DataColumn("date", System.Type.GetType("System.DateTime"))); 
     scoreboard.Columns.Add(new DataColumn("synced", System.Type.GetType("System.Boolean"))); 

     scoreboard.AcceptChanges(); 
     return scoreboard; 
    } 

    private void Run() 
    { 
     // For additional security Pin the key. 
     GCHandle gch = GCHandle.Alloc(sSecretKey, GCHandleType.Pinned); 

     // Remove the Key from memory. 
     ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2); 
     gch.Free(); 
    } 
} 
} 
+1

Просто свободное наблюдение: независимо от того, насколько хорошо ваше шифрование. Если вы храните шифрование в виде строки в своем приложении, это небезопасно. – Toad

+2

Привет, Рейнер, полностью согласен. Табло только для маленькой игры и предназначено только для того, чтобы остановить самый очевидный уровень обмана. Я не смотрел на более безопасные способы сделать это, поскольку казалось, что он убит. Спасибо за ваш вклад, хотя :) – Jon

ответ

0

Вы могли бы хотеть, чтобы проверить эту ссылку из: http://blogs.msdn.com/shawnfa/archive/2005/11/10/491431.aspx

Это говорит о проблемах с шифрования/дешифрования и кодирования ASCII ,

+0

Я, возможно, неправильно понимаю статью, но я не думаю, что это моя проблема здесь. хотя это может стать проблемой в будущем, например, многоязычными вещами. Унаследованное приложение может открыть файл без проблем, я буквально скопировал его код (вырезать и вставить) в новое приложение и запустить его. Если у старого приложения нет проблем, я не знаю, почему новый. – Jon

+0

Если старое приложение написано в .net 1.1, а новое - в .net 2.0 или выше, то кодировка ascii будет большой проблемой. В основном потому, что они «исправили» его в фреймворке 2.0 ... – NotMe

+0

Итак, вам нужно избавиться от всего кодирования ASCII – NotMe

4

Это выглядит как код для расшифровки файла и десериализации вашего объекта табло. Нам действительно нужно сравнить исходную сторону шифрования, если вы можете опубликовать ее.

У меня есть два замечания из кода дешифрования:

  • Установка капельницы так же, как ключ не выглядит правильно (хотя это может быть правильным, если это то, что делает ваш код шифрования)
  • Это действительно вопросительные знаки в SSecretKey? Могут ли они быть управляемыми или высокоуровневыми персонажами, ставшими жертвой неправильного кодирования и/или неправильной загрузки?

Добавлено: Спасибо за обновление. Немного поисковой системы говорит о том, что Bad Data часто вызвано тем, что дешифрованные данные не являются точно тем, что было выведено из шифрования, это место для фокусировки (но продолжайте искать правильность ключевой строки). Я должен признать, что я немного из моей глубины в C#, поэтому ниже приводятся только предложения:

  • В writeScoreboardToFile вы пишете XML в MemoryStream, а затем записать содержимое этого потока на ваш CryptoStream. Есть ли причина, по которой вы не пишете напрямую в CryptoStream?
  • Правомерно ли установить ms.Position? Делает ли ms.Seek(0,SeekOrigin.Begin) какой-либо разницей?
  • Возможно, вам нужно будет позвонить cryptostream.FlushFinalBlock(), прежде чем закрыть его, из MSDN неясно, будет ли он автоматически вызван.
  • Зашифрованные данные являются бинарными, вам может потребоваться использовать BinaryReader и BinaryWriter, чтобы избежать его разрыва при кодировании, как указал Крис.
  • Когда именно вызывается Run()? Если я правильно понял, это обнуление строки секретного ключа - очевидно, вы не хотите, чтобы это произошло до того, как вы закончите создавать криптографические преобразования.

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

+0

Привет, спасибо за ввод. Я добавил полный код для вас. Да, я думаю, что они были вопросительными знаками. Думаю, придется вернуться к старым вещам, чтобы проверить. – Jon

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