С# Зашифровать сериализованный файл перед записью на диск

Скажем, моя программа имеет класс под названием "клиент", а класс клиента сериализуется, поэтому я могу читать и записывать его на диск. Класс клиента содержит конфиденциальную информацию, которую я хочу зашифровать, единственный способ, которым я знаю, что я могу сохранить файл в безопасности, будет:

1-Сериализовать файл на диск

2-Reopen и загрузить файл

3-Шифровать файл

4-Перезаписать файл на диск

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

Вместо этого я хотел бы:

1-Создать файл в памяти

2-Шифровать файл в памяти

3-Записать зашифрованный файл на диск

Возможно ли это? Если это так? Спасибо заранее.

Ответы

Ответ 1

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

using (var fileStream = File.OpenWrite(theFileName))
using (var memoryStream = new MemoryStream())
{
    // Serialize to memory instead of to file
    var formatter = new BinaryFormatter();
    formatter.Serialize(memoryStream, customer);

    // This resets the memory stream position for the following read operation
    memoryStream.Seek(0, SeekOrigin.Begin);

    // Get the bytes
    var bytes = new byte[memoryStream.Length];
    memoryStream.Read(bytes, 0, (int)memoryStream.Length);

    // Encrypt your bytes with your chosen encryption method, and write the result instead of the source bytes
    var encryptedBytes = yourCrypto.Encrypt(bytes);
    fileStream.Write(encryptedBytes, 0, encryptedBytes.Length);
}

Ответ 2

Вы можете использовать CryptoStream для шифрования в то же время, когда вы сериализуете класс в файл:

byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8 }; // Where to store these keys is the tricky part, 
    // you may need to obfuscate them or get the user to input a password each time
byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8 };
string path = @"C:\path\to.file";

DESCryptoServiceProvider des = new DESCryptoServiceProvider();

// Encryption
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
using (var cryptoStream = new CryptoStream(fs, des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
    BinaryFormatter formatter = new BinaryFormatter();

    // This is where you serialize the class
    formatter.Serialize(cryptoStream, customClass);
}

// Decryption
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var cryptoStream = new CryptoStream(fs, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
    BinaryFormatter formatter = new BinaryFormatter();

    // This is where you deserialize the class
    CustomClass deserialized = (CustomClass)formatter.Deserialize(cryptoStream);
}

Ответ 3

Вполне возможно,

Давайте скажем, что класс выглядит как

public class Customer
{
public string Name{get;set;}
public int salary {get;set;}
}

Вы можете зашифровать данные, хранящиеся в свойствах объекта поэтому customer.Name = 'ABC' может стать клиентом. Name = 'WQW' что-то вроде этого

чем сериализовать его.

При десериализации, когда вам нужно показать данные, которые вы должны расшифровать, прежде чем показывать данные пользователю

надеюсь, что эта помощь

Ответ 4

Я бы создал класс для сериализации, который предлагает свойство. чтение его (дающее имя файла) возвращает десериализованные объекты, записывая его (также давая имя файла), сериализует объект. Я добавил второе свойство с паролем String. При его использовании вы можете зашифровать сериализованную строку объекта и nwrite на диск или при чтении с нее 1. зашифровать, а затем десериализовать.

Чтобы зашифровать, я бы рекомендовал хеш-функцию из пароля вместо прямого использования. К сожалению, у меня есть только пример кода в vb.net:

Function Encrypt(ByVal data As String, ByVal password As String) As String
  Dim pdb As New Rfc2898DeriveBytes(password, Salt)
  Dim alg As Rijndael = Rijndael.Create()
  alg.Key = pdb.GetBytes(32)
  alg.IV = pdb.GetBytes(16)
  Dim ms As New IO.MemoryStream
  Dim cs As New CryptoStream(ms, alg.CreateEncryptor, CryptoStreamMode.Write)
  cs.Write(System.Text.Encoding.Default.GetBytes(data), 0, data.Length)
  cs.Close()
  ms.Close()
  Return Convert.ToBase64String(ms.ToArray)
End Function

Private Salt As Byte() = {100, 86, 34, 53, 11, 224, 145, 123, _
                                 237, 213, 12, 124, 45, 65, 71, 127, _
                                 135, 165, 234, 164, 127, 234, 231, 211, _
                                 10, 9, 114, 234, 44, 63, 75, 12}


Function Decrypt(ByVal data As String, ByVal password As String) As String
  Dim pdb As New Rfc2898DeriveBytes(password, Salt)
  Dim alg As Rijndael = Rijndael.Create()
  alg.Key = pdb.GetBytes(32)
  alg.IV = pdb.GetBytes(16)

  Dim ms As New IO.MemoryStream
  Dim cs As New CryptoStream(ms, alg.CreateDecryptor, CryptoStreamMode.Write)
  cs.Write(Convert.FromBase64String(data), 0, Convert.FromBase64String(data).Length)
  cs.Close()
  ms.Close()
  Return System.Text.Encoding.Default.GetString(ms.ToArray)
End Function

и

Function EncryptWithHash(ByVal data As String, ByVal passToHash As String) As String
  Dim _hash As String = getMd5Hash(passToHash)
  Dim _result As String = Encrypt(data, _hash)
  Return _result
End Function

Function DecryptWithHash(ByVal data As String, ByVal passToHash As String) As String
  Dim _hash As String = getMd5Hash(passToHash)
  Dim _result As String = Encrypt(data, _hash)
  Return _result
End Function

Function getMd5Hash(ByVal input As String) As String
  ' Create a new instance of the MD5CryptoServiceProvider object.
  Dim md5Hasher As New MD5CryptoServiceProvider()

  ' Convert the input string to a byte array and compute the hash.
  Dim data As Byte() = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input))

  ' Create a new Stringbuilder to collect the bytes
  ' and create a string.
  Dim sBuilder As New StringBuilder()

  ' Loop through each byte of the hashed data 
  ' and format each one as a hexadecimal string.
  Dim i As Integer
  For i = 0 To data.Length - 1
    sBuilder.Append(data(i).ToString("x2"))
  Next i

  ' Return the hexadecimal string.
  Return sBuilder.ToString()
End Function

свойство в моем коде имеет Get:

    Dim _dataC As String = ReadFile(filename)

    Dim _dataR As String = Crypt.Decrypt(_dataC, password)

    Dim _result = tmpS.ReadString(_dataR)

и Set:

    Dim _tmpS As New Custom.Serialization(Of Object)
    Dim _tmpRaw As String = _tmpS.WriteString(value)

    Dim _tmpCrypt As String = Crypt.Encrypt(_tmpRaw, password)

WriteFile(tmpPath, _tmpCrypt)

вам нужно будет определить свою собственную сериализацию и прочитать/записать файлы:

My.Computer.FileSystem.WriteAllText(filename, data, False)

_result = My.Computer.FileSystem.ReadAllText(FileName)