воскресенье, 4 августа 2013 г.

C# шифрование DataSet при сохранение в XML

При работе с DataSet в dotNet есть две очень удобные функции - ReadXML и WriteXML, которые очень удобно использовать если требуется хранить небольшие объёмы данных и подключать БД не имеет смысла. Но что делать если требуется шифрование данных файлов, чтобы никто посторонний не мог их прочитать?

После недолго гугления было решено использовать алгоритм Rijndael, как не имеющий на данный момент способов взлома. Прочитать на википедии про него можно тут ru.wikipedia.org/wiki/Rijndael

Также выбор на него пал потому, что C# имеет встроенную реализацию данного алгоритма и позволяет достаточно просто с ним работать. Подробнее на MSDN http://msdn.microsoft.com/ru-ru/library/system.security.cryptography.rijndael.aspx


Теперь перейдём непосредственно к семплам кода - 
        #region Password SaveLoadDataSet
        private void saveDataSet()
        {
           SetDataSet("data.xml", dataSet1, "TestPassword");
        }
 
        private void loadDataSet()
        {
            dataSet1.Clear();
 
            if (File.Exists("data.xml") == true)
            {                
                GetDataSet("data.xml", "TestPassword", dataSet1);
            }            
        }
 
        public void GetDataSet(string file, string key, DataSet ds)
        {
            Rijndael crypto = Rijndael.Create();
 
            crypto.IV = ASCIIEncoding.ASCII.GetBytes("UserName".PadRight(16, 'x'));
            crypto.Key = ASCIIEncoding.ASCII.GetBytes(key.PadRight(16, 'x'));
            crypto.Padding = PaddingMode.Zeros;
 
            using (FileStream stream = new FileStream(file, FileMode.Open))
            {
                using (CryptoStream cryptoStream = new CryptoStream(stream, crypto.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    ds.ReadXml(cryptoStream);
                    cryptoStream.Close();
                    stream.Close();
                }
            }            
        }
 
        public void SetDataSet(string file, DataSet ds, string key)
        {
            Rijndael crypto = Rijndael.Create();
 
            crypto.IV = ASCIIEncoding.ASCII.GetBytes("UserName".PadRight(16, 'x'));
            crypto.Key = ASCIIEncoding.ASCII.GetBytes(key.PadRight(16, 'x'));
            crypto.Padding = PaddingMode.Zeros;
 
            File.Delete(file);
 
            using (FileStream stream = new FileStream(file, FileMode.OpenOrCreate))
            {
                using (CryptoStream cryptoStream = new CryptoStream(stream, crypto.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    ds.WriteXml(cryptoStream);
                    cryptoStream.Flush();
                    stream.Flush();
                    cryptoStream.Close();
                    stream.Close();
                }
            }
        }
        #endregion

PS: Внимание! Данный код не проверяет корректность пароля - он только для примера, в случае неверного пароля программа просто вылетает с экзепшеном - так что проверяйте сами.