С# Зашифровать сериализованный файл перед записью на диск
Скажем, моя программа имеет класс под названием "клиент", а класс клиента сериализуется, поэтому я могу читать и записывать его на диск. Класс клиента содержит конфиденциальную информацию, которую я хочу зашифровать, единственный способ, которым я знаю, что я могу сохранить файл в безопасности, будет:
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)