gpt4 book ai didi

c# - 如何在序列化后加密保存二进制流并读回?

转载 作者:太空狗 更新时间:2023-10-29 20:25:40 25 4
gpt4 key购买 nike

当我想在二进制序列化后加密二进制流并将其保存到文件时,我在使用 CryptoStream 时遇到了一些问题。我收到以下异常

System.ArgumentException : Stream was not readable.

任何人都可以告诉我如何加密二进制流并将其保存到文件并正确反序列化吗?

代码如下:

class Program
{
public static void Main(string[] args)
{
var b = new B {Name = "BB"};
WriteFile<B>(@"C:\test.bin", b, true);
var bb = ReadFile<B>(@"C:\test.bin", true);

Console.WriteLine(b.Name == bb.Name);
Console.ReadLine();
}

public static T ReadFile<T>(string file, bool decrypt)
{
T bObj = default(T);
var _binaryFormatter = new BinaryFormatter();
Stream buffer = null;

using (var stream = new FileStream(file, FileMode.OpenOrCreate))
{
if(decrypt)
{
const string strEncrypt = "*#4$%^.++q~!cfr0(_!#$@$!&#&#*&@(7cy9rn8r265&$@&*E^184t44tq2cr9o3r6329";
byte[] dv = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
CryptoStream cs;
DESCryptoServiceProvider des = null;

var byKey = Encoding.UTF8.GetBytes(strEncrypt.Substring(0, 8));
using (des = new DESCryptoServiceProvider())
{
cs = new CryptoStream(stream, des.CreateEncryptor(byKey, dv), CryptoStreamMode.Read);
}
buffer = cs;
}
else
buffer = stream;
try
{
bObj = (T) _binaryFormatter.Deserialize(buffer);
}
catch(SerializationException ex)
{
Console.WriteLine(ex.Message);
}
}

return bObj;
}

public static void WriteFile<T>(string file, T bObj, bool encrypt)
{
var _binaryFormatter = new BinaryFormatter();
Stream buffer;

using (var stream = new FileStream(file, FileMode.Create))
{
try
{
if(encrypt)
{
const string strEncrypt = "*#4$%^.++q~!cfr0(_!#$@$!&#&#*&@(7cy9rn8r265&$@&*E^184t44tq2cr9o3r6329";
byte[] dv = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
CryptoStream cs;
DESCryptoServiceProvider des = null;

var byKey = Encoding.UTF8.GetBytes(strEncrypt.Substring(0, 8));
using (des = new DESCryptoServiceProvider())
{
cs = new CryptoStream(stream, des.CreateEncryptor(byKey, dv), CryptoStreamMode.Write);
buffer = cs;
}
}
else
buffer = stream;

_binaryFormatter.Serialize(buffer, bObj);
buffer.Flush();
}
catch(SerializationException ex)
{
Console.WriteLine(ex.Message);
}
}
}
}

[Serializable]
public class B
{
public string Name {get; set;}
}

它抛出如下序列化异常

输入流不是有效的二进制格式。起始内容(以字节为单位)是:3F-17-2E-20-80-56-A3-2A-46-63-22-C4-49-56-22-B4-DA ...

最佳答案

如果你这样做,它应该可以工作:

// A: encrypting when writing
// 1. create backing storage stream. In your case a file stream
using(Stream innerStream = File.Create(path))
// 2. create a CryptoStream in write mode
using(Stream cryptoStream = new CryptoStream(innerStream, encryptor, CryptoStreamMode.Write))
{
// 3. write to the cryptoStream
binaryFormatter.Serialize(cryptoStream, obj);
}

// B: decrypting when reading
// 1. create backing storage stream. In your case a file stream
using(Stream innerStream = File.Open(path, FileMode.Open))
// 2. create a CryptoStream in read mode
using(Stream cryptoStream = new CryptoStream(innerStream, decryptor, CryptoStreamMode.Read))
{
// 3. read from the cryptoStream
obj = binaryFormatter.Deserialize(cryptoStream);
}

您的代码有几个问题:

  1. 您在阅读时使用了加密器。这可能是一个错字,但它应该是一个解密器。

  2. 您正在刷新 buffer,但这在使用 CryptoStream 时是不够的。加密器和解密器在固定大小的 block 上工作。最后一个 block 可能没有那个大小,因此需要特殊处理。最后一个 block 是在流关闭而不是刷新之前写入的 block 。在 CryptoStream 上刷新没有任何用处,因为它不能写入任何小于加密器/解密器输入 block 大小的东西,除非它是最后要写入的东西。最重要的是,一般来说,无论发生什么情况,您都应该始终关闭您的流。 using 语句是推荐的做法:

    using(buffer)
    _binaryFormatter.Serialize(buffer, bObj);

关于c# - 如何在序列化后加密保存二进制流并读回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4584135/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com