二进制格式化程序反序列化时CryptoStream问题
我在这里有点绝望了。我正在尝试将带有序列化对象的加密文件写入磁盘,然后检索该文件,解密该文件并将对象反序列化回来。
更新: 我将代码重构为:
using (Stream innerStream = File.Create(this.GetFullFileNameForUser(securityContext.User, applicationName)))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateEncryptor(), CryptoStreamMode.Write))
{
// 3. write to the cryptoStream
//BinaryFormatter bf = new BinaryFormatter();
//bf.Serialize(cryptoStream, securityContext);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
xs.Serialize(cryptoStream, securityContext);
}
}
using (Stream innerStream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read))
{
//BinaryFormatter bf = new BinaryFormatter();
//return (SecurityContextDTO)bf.Deserialize(cryptoStream);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
//CryptographicException here
return (SecurityContextDTO)xs.Deserialize(cryptoStream);
}
}
现在我在反序列化时遇到加密异常:错误数据
原始:
我正在这样做:
public void StoreToFile(SecurityContextDTO securityContext, string applicationName)
{
if (securityContext.LoginResult.IsOfflineMode == false)
{
Stream stream = null;
CryptoStream crStream = null;
try
{
TripleDESCryptoServiceProvider cryptic = GetCryptoProvider();
stream = File.Open(this.GetFullFileNameForUser(securityContext.User, applicationName), FileMode.Create);
crStream = new CryptoStream(stream,
cryptic.CreateEncryptor(), CryptoStreamMode.Write);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(crStream, securityContext);
}
catch(Exception)
{
throw;
}
finally
{
if (crStream != null)
crStream.Close();
}
}
}
public SecurityContextDTO RetrieveFromFile(UserDTO user,string applicationName)
{
SecurityContextDTO objectToSerialize;
Stream stream = null;
CryptoStream crStream=null;
try
{
stream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open);
crStream= new CryptoStream(stream,
GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read);
BinaryFormatter bFormatter = new BinaryFormatter();
//Exception here
objectToSerialize = (SecurityContextDTO)bFormatter.Deserialize(crStream);
}
catch (Exception)
{
objectToSerialize = null;
}
finally
{
if (crStream!=null)
crStream.Close();
}
return objectToSerialize;
}
private static TripleDESCryptoServiceProvider GetCryptoProvider()
{
TripleDESCryptoServiceProvider cryptic = new TripleDESCryptoServiceProvider();
try
{
cryptic.Key = ASCIIEncoding.ASCII.GetBytes(CrypKey);
Rfc2898DeriveBytes db = new Rfc2898DeriveBytes("sdddsdsd", 8);
cryptic.IV = db.GetBytes(8);
}
catch (Exception)
{
throw;
}
finally
{
cryptic.Dispose();
}
return cryptic;
}
加密和写入工作正常,文件出现在磁盘上并且内容在那里(当然是加密的) 。但是当我调用检索方法时,我总是得到 SerializationException
二进制流“30”不包含有效的 BinaryHeader。可能的原因是序列化和反序列化之间无效的流或对象版本更改。
当我将加密方法排除在外时,一切正常。
I'm getting a bit desperate here. I'm trying to write an encrypted file with a serialized object to disk and later retrieve the file, decrypt it and deserialize the object back.
UPDATE:
I refactored the code to this:
using (Stream innerStream = File.Create(this.GetFullFileNameForUser(securityContext.User, applicationName)))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateEncryptor(), CryptoStreamMode.Write))
{
// 3. write to the cryptoStream
//BinaryFormatter bf = new BinaryFormatter();
//bf.Serialize(cryptoStream, securityContext);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
xs.Serialize(cryptoStream, securityContext);
}
}
using (Stream innerStream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read))
{
//BinaryFormatter bf = new BinaryFormatter();
//return (SecurityContextDTO)bf.Deserialize(cryptoStream);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
//CryptographicException here
return (SecurityContextDTO)xs.Deserialize(cryptoStream);
}
}
Now I'm getting a cryptographic exception on deserialize: Bad Data
ORIGINAL:
I'm doing this:
public void StoreToFile(SecurityContextDTO securityContext, string applicationName)
{
if (securityContext.LoginResult.IsOfflineMode == false)
{
Stream stream = null;
CryptoStream crStream = null;
try
{
TripleDESCryptoServiceProvider cryptic = GetCryptoProvider();
stream = File.Open(this.GetFullFileNameForUser(securityContext.User, applicationName), FileMode.Create);
crStream = new CryptoStream(stream,
cryptic.CreateEncryptor(), CryptoStreamMode.Write);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(crStream, securityContext);
}
catch(Exception)
{
throw;
}
finally
{
if (crStream != null)
crStream.Close();
}
}
}
public SecurityContextDTO RetrieveFromFile(UserDTO user,string applicationName)
{
SecurityContextDTO objectToSerialize;
Stream stream = null;
CryptoStream crStream=null;
try
{
stream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open);
crStream= new CryptoStream(stream,
GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read);
BinaryFormatter bFormatter = new BinaryFormatter();
//Exception here
objectToSerialize = (SecurityContextDTO)bFormatter.Deserialize(crStream);
}
catch (Exception)
{
objectToSerialize = null;
}
finally
{
if (crStream!=null)
crStream.Close();
}
return objectToSerialize;
}
private static TripleDESCryptoServiceProvider GetCryptoProvider()
{
TripleDESCryptoServiceProvider cryptic = new TripleDESCryptoServiceProvider();
try
{
cryptic.Key = ASCIIEncoding.ASCII.GetBytes(CrypKey);
Rfc2898DeriveBytes db = new Rfc2898DeriveBytes("sdddsdsd", 8);
cryptic.IV = db.GetBytes(8);
}
catch (Exception)
{
throw;
}
finally
{
cryptic.Dispose();
}
return cryptic;
}
Encrypting and writing works fine, the file appears on the disk and the content is there (encrypted of course). But when I call the retrieve method I always get a SerializationException
Binary stream '30' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
When I leave the cryptographic methods out everything works fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所以,
您意识到在这段代码中
您将始终处置提供程序,这意味着您始终使用随机密钥和 iv
So,
You realize that in this code
you will ALWAYS dispose of the provider meaning you are always using a random key and iv
你很接近。但是,您传递到 CryptoStream 创建中的流始终、始终、始终是将保存最终结果的缓冲区。它不是保存您想要加密或解密的数据的流。我把重点放在那里是因为我记得第一次学习这个并且我完全按照你在做的事情做。所以这里:
请注意,在这两种情况下,CryptoStream 都是用空白输出流初始化的。您的流要稍后才会进入画面。因此,在写入期间,您将执行以下操作:
在读取期间,您将:
因此,为了省去一些麻烦,这里有一个很好的简单对称方法,它将执行加密和解密。这和你的唯一区别是我直接在字节数组上工作,但也许这种增强可以是一种练习:
并且要调用它,你可能会做这样的事情:
同样,你会做一些稍微不同的事情来使用流,但希望你能明白要点。它将是您需要输入序列化器的任何流,而不是 MemoryStream。
You are close. However, the stream you pass into the creation of CryptoStream is always, always, always the buffer that will hold your end result. It is not the stream that holds the data you want to encrypt or decrypt. I put the emphasis in there because I remember learning this for the first time and I did exactly what you were doing. So here:
Notice in both cases, CryptoStream is being initialized with a blank output stream. Your stream does not enter into the picture until later. So, during a write, you will do the following:
And during the read, you will:
So, to save you some trouble, here's a nice simple Symmetric method that will perform both encryption and decryption. The only difference between this and yours is that I am working directly on byte arrays, but perhaps that augmentation can be an exercise:
And to call it, you might do something like this:
Again, you'll do something slightly different to work with streams, but hopefully you get the gist. Instead of MemoryStream, it will be whatever stream you need to feed into your serializer.
以前的一些帖子可以使用:
如何使用 RijndaelManaged 和 PKCS5 加密 vb.net 中的字符串填充?
BinaryFormatter是否应用任何压缩?
稍后,您可以看到我如何将压缩、加密和序列化叠加起来。它有效。
Some previous posts that can be of use:
How do I encrypt a string in vb.net using RijndaelManaged, and using PKCS5 padding?
Does BinaryFormatter apply any compression?
In later, you can see how I stacked compression with encryption with serialization. And it works.