C# 在写入磁盘之前加密序列化文件

发布于 2024-11-04 22:57:11 字数 357 浏览 1 评论 0原文

假设我的程序有一个名为“customer”的类,并且该客户类是可序列化的,因此我可以将其读取和写入磁盘。客户类保存我想要加密的敏感信息,我知道可以保证文件安全的唯一方法是:

1-将文件序列化到磁盘

2-重新打开并加载文件

3-加密文件

4-将文件重写到磁盘

这可行,但存在文件可能在未加密状态下被拦截的风险,而且这确实是真的效率低下。

相反,我想:

1-在内存中创建文件

2-加密内存中的文件

3-将加密文件写入磁盘

这可能吗?如果是怎么办?提前致谢。

Let's say my program has a class called "customer" and the customer class is serializable so I can read and write it to disk. The customer class holds sensitive information that I want to encrypt, the only way I know I could keep the file safe would be to:

1-Serialize the file to disk

2-Reopen and load the file

3-Encrypt the file

4-Rewrite file to disk

This would work, but there is a risk that the file could be intercepted in it's unencrypted state and furthermore this is just really inefficient.

Instead I would like to:

1-Create file in memory

2-Encrypt file in memory

3-Write encrypted file to disk

Is this possible? If it is how? Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白衬杉格子梦 2024-11-11 22:57:11

您可以在将类序列化到文件的同时使用 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);
}

You can use a CryptoStream to do the encryption at the same time as you serialize the class to a file:

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);
}
你穿错了嫁妆 2024-11-11 22:57:11

除了评论中表达的担忧之外,如果您所问的只是如何使用内存中的字节并且仅将它们写入文件一次,那么只需首先将对象序列化到内存流即可。加密这些字节并将其写入文件。

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);
}

Aside from the concerns expressed in the comments, if all you are asking is how to work with the bytes in memory and only write them to the file once, just serialize your object to a memory stream first. Encrypt those bytes and write them to the file.

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);
}
你是年少的欢喜 2024-11-11 22:57:11

很有可能,

假设您的类看起来像

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

您可以加密对象属性中保存的数据
所以 customer.Name = 'ABC' 可能会变成 customer.Name = 'WQW' 类似的东西

而不是序列化它。

在反序列化时,当您必须显示数据时,您必须在向用户显示数据之前对其进行解密

希望这有帮助

Its quite possible,

Lets say you class looks like

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

You could encrypt the data held in properties of the object
so customer.Name = 'ABC' could become customer.Name = 'WQW' something like that

than serialize it.

On deserialization, when you have to show the data you have to decrypt it before showing the data to the user

hope this help

攒一口袋星星 2024-11-11 22:57:11

我将创建一个提供属性的序列化类。读取它(给出文件名)会返回反序列化的对象,写入它(也给出文件名)会序列化对象。
我添加了第二个带有字符串密码的属性。使用它时,您可以加密序列化对象字符串和 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)

I would create a class for serialization which offers a property. reading it (giving a filename) returns the deserialized objects, writing to it (also giving a filename) serializes the object.
I added a second property with a String password. When using it you can encrypt the serialized object string and the nwrite to disk or when reading from it 1. encrypt, then deserialize.

To encrypt, I would recommend a hash function from the password instead of directly using it.
Unfortunately I only have a code example in 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

and

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

the property in my code has Get:

    Dim _dataC As String = ReadFile(filename)

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

    Dim _result = tmpS.ReadString(_dataR)

and 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)

you will have to define your own Serialization, and to read/write Files:

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

_result = My.Computer.FileSystem.ReadAllText(FileName)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文