反序列化时的BinaryFormatter和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。 可能的原因是序列化和反序列化的无效流或对象版本的变化。

当我离开的加密方法了一切工作正常。

--------------解决方案-------------

所以,

你会意识到,在这段代码

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(); // <------- Don't do this until you are done decrypting.
}
return cryptic;
}

你将永远处置提供商的你总是使用随机密钥和IV意思

你靠近。 然而,你传进创作的CryptoStream流总是,总是,总是会牵着你的最终结果缓冲区。 并不是说持有要加密或解密的数据流。 我将重点放在那里,因为我记得这种学习是第一次,我做你在做什么。 所以在这里:

// this is for encryption
var memStreamEncryptedData = new MemoryStream();
var encryptStream = new CryptoStream(memStreamEncryptedData,
transform, CryptoStreamMode.Write);

// this is for decryption
var memStreamDecryptedData = new MemoryStream();
var decryptStream = new CryptoStream(memStreamDecryptedData,
transform, CryptoStreamMode.Write);

在这两种情况下通知,CryptoStream的正在与一个空白输出流初始化。 你流不进入画面,直到后来。 因此,在写入期间,你会做以下几点:

encryptStream.Write(dataToBeEncrypted);
encryptStream.FlushFinalBlock();
encryptStream.Close();
// memStreamEncryptedData now safely holds your encrypted data

和读取过程中,你会:

decryptStream.Write(dataToBeDecrypted);
encryptStream.FlushFinalBlock();
encryptStream.Close();
// memStreamDecryptedData now safely holds your decrypted data

所以,为您节省了一些麻烦,这里将执行加密和解密一个不错的简单方法对称。 这和你之间的唯一区别是,我的字节数组直接合作,但也许是隆胸可以是一个练习:

public static byte[] Symmetric(bool encrypt, byte[] plaintext, string ikey)
{
if (plaintext.Length == 0) return plaintext;

// setting up the services can be very expensive, so I'll cache them
// into a static dictionary.
SymmetricSetup setup;
if (!_dictSymmetricSetup.TryGetValue(ikey, out setup))
{
setup = new SymmetricSetup();
setup.des = new DESCryptoServiceProvider { Mode = CipherMode.CBC,
Padding = PaddingMode.Zeros };
setup.hash = Hash(Encoding.ASCII.GetBytes(ikey));
setup.key = setup.hash.ForceLength(8, 0);
setup.IV = Encoding.ASCII.GetBytes("init vec");
setup.des.Key = setup.key;
setup.des.IV = setup.IV;

setup.encrypt = setup.des.CreateEncryptor(setup.des.Key, setup.des.IV);
setup.decrypt = setup.des.CreateDecryptor(setup.des.Key, setup.des.IV);
_dictSymmetricSetup[ikey] = setup;
}

var transform = encrypt ? setup.encrypt : setup.decrypt;

var memStreamEncryptedData = new MemoryStream();

var encStream = new CryptoStream(memStreamEncryptedData, transform, CryptoStreamMode.Write);

if (encrypt)
encStream.Write(new[] {(byte) ((8 - (plaintext.Length + 1)%8)%8)}, 0, 1);

encStream.Write(plaintext, 0, plaintext.Length);
encStream.FlushFinalBlock();
encStream.Close();

memStreamEncryptedData.Flush();

var ciphertext = memStreamEncryptedData.ToArray();

byte b;

if (!encrypt)
if (byte.TryParse("" + ciphertext[0], out b))
ciphertext = ciphertext.Skip(1).Take(ciphertext.Length - b - 1).ToArray();

return ciphertext;
}

并调用它,你可能会做这样的事情:

static public byte[] DecryptData(this byte[] source, string password) {
return Symmetric(false, source, password);
}

static public byte[] EncryptData(this byte[] source, string password) {
return Symmetric(true, source, password);
}

同样,你会做一些稍微不同的用流的工作,但希望你得到的要点。 取而代之的MemoryStream的,这将是你需要喂到你的串行任何流。

以前的一些帖子,可以使用:

我如何使用RijndaelManaged的,并使用PKCS5加密填充在vb.net中的字符串?

是否适用BinaryFormatter的任何压缩?

在以后,你可以看到我是如何叠压缩与加密序列化。 和它的作品。

分类:C# 时间:2015-03-15 人气:0
本文关键词: .NET,文件IO,对称加密
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.565 (s). 10 q(s)