Я в процессе перезаписи старого приложения. Старое приложение хранило данные в файле табло, который был зашифрован следующим кодом:.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();
}
}
}
Просто свободное наблюдение: независимо от того, насколько хорошо ваше шифрование. Если вы храните шифрование в виде строки в своем приложении, это небезопасно. – Toad
Привет, Рейнер, полностью согласен. Табло только для маленькой игры и предназначено только для того, чтобы остановить самый очевидный уровень обмана. Я не смотрел на более безопасные способы сделать это, поскольку казалось, что он убит. Спасибо за ваш вклад, хотя :) – Jon