如何使用LINQ到XML读取/编写加密的XML文件?

时间:2023-01-29 09:55:40

I would like to read/write encrypted XML files using LINQ to XML. Does anyone know how to use encryption algorithms built into the .NET Framework to encrypt the Stream used by the XDocument object?

我希望使用LINQ到XML来读取/编写加密的XML文件。有谁知道如何使用内置在。net框架中的加密算法来加密XDocument对象使用的流吗?

I did try it, but you can't set the CryptoStream to Read/Write access. It only support Read or Write, which causes LINQ to XML to throw an exception.

我确实尝试过,但是您不能设置加密流来读取/写入访问。它只支持读或写,这会导致LINQ to XML抛出异常。

Update: It would be nice to read/write the document "on the fly", but I am only required to read the encrypted xml file, manipulate it, then write it back out encrypted again.

更新:“动态”读/写文档是很好的,但是我只需要读取加密的xml文件,对其进行操作,然后再将其重新加密。

2 个解决方案

#1


8  

The easiest approach is probably an XDocument.Load(), Linq around, then XDocument.Save(). From a quick test app (go easy on non-disposed resources):

最简单的方法可能是XDocument.Load()、Linq,然后是XDocument.Save()。从一个快速测试应用程序(在非处置资源上轻松操作):

XDocument writeContacts = new XDocument(
   new XElement("contacts",
      new XElement("contact",
         new XElement("name", "Patrick Hines"),
         new XElement("phone", "206-555-0144",
             new XAttribute("type", "home")),
         new XElement("phone", "425-555-0145",
             new XAttribute("type", "work")),
         new XElement("address",
            new XElement("street1", "123 Main St"),
            new XElement("city", "Mercer Island"),
            new XElement("state", "WA"),
            new XElement("postal", "68042")
         )
      )
   )
);

Rijndael RijndaelAlg = Rijndael.Create();

FileStream writeStream = File.Open("data.xml", FileMode.Create);
CryptoStream cStream = new CryptoStream(writeStream,
    RijndaelAlg.CreateEncryptor(RijndaelAlg.Key, RijndaelAlg.IV),
    CryptoStreamMode.Write);

StreamWriter writer = new StreamWriter(cStream);

writeContacts.Save(writer);

writer.Flush();
writer.Close();

FileStream readStream = File.OpenRead("data.xml");

cStream = new CryptoStream(readStream,
  RijndaelAlg.CreateDecryptor(RijndaelAlg.Key, RijndaelAlg.IV),
  CryptoStreamMode.Read);

XmlTextReader reader = new XmlTextReader(cStream);

XDocument readContacts = XDocument.Load(reader);

//manipulate with Linq and Save() when needed

Swap your favorite ICryptoTransform into the CryptoStream.

将您最喜欢的ICryptoTransform交换到加密流中。

#2


0  

[update: kudos to Corbin March, who (in the same time) wrote the same, but in code!]

[更新:向Corbin March致敬,他(同时)也写了同样的东西,但是是用代码写的!]

Most streams are one way. I imagine you'd have to:

大多数溪流是一种方式。我想你不得不:

  • create a CryptoStream reading from the (file etc)
  • 创建从(文件等)读取的加密流
  • read the data (for example into XDocument)
  • 读取数据(例如,到XDocument中)
  • do your code (read the document, make changes, etc)
  • 执行您的代码(读取文档,进行更改等)
  • crate a new CryptoStream writing to the (file etc) [starting with the same IV etc)
  • 将一个新的加密流写入(文件等)[以相同的IV等开始)
  • save the docuemnt to the stream
  • 将docuemnt保存到流中

Depending on what the underlying stream is (FileStream, MemoryStream, etc) you may well also have to completely close/re-open it between the read and write (i.e. the CryptoStream will probably feel ownership of the base-stream, and will .Close() it).

根据底层流是什么(FileStream、MemoryStream等),您很可能还必须在读和写之间完全关闭/重新打开它(例如,加密流可能会感到基本流的所有权,并将. close()它)。

#1


8  

The easiest approach is probably an XDocument.Load(), Linq around, then XDocument.Save(). From a quick test app (go easy on non-disposed resources):

最简单的方法可能是XDocument.Load()、Linq,然后是XDocument.Save()。从一个快速测试应用程序(在非处置资源上轻松操作):

XDocument writeContacts = new XDocument(
   new XElement("contacts",
      new XElement("contact",
         new XElement("name", "Patrick Hines"),
         new XElement("phone", "206-555-0144",
             new XAttribute("type", "home")),
         new XElement("phone", "425-555-0145",
             new XAttribute("type", "work")),
         new XElement("address",
            new XElement("street1", "123 Main St"),
            new XElement("city", "Mercer Island"),
            new XElement("state", "WA"),
            new XElement("postal", "68042")
         )
      )
   )
);

Rijndael RijndaelAlg = Rijndael.Create();

FileStream writeStream = File.Open("data.xml", FileMode.Create);
CryptoStream cStream = new CryptoStream(writeStream,
    RijndaelAlg.CreateEncryptor(RijndaelAlg.Key, RijndaelAlg.IV),
    CryptoStreamMode.Write);

StreamWriter writer = new StreamWriter(cStream);

writeContacts.Save(writer);

writer.Flush();
writer.Close();

FileStream readStream = File.OpenRead("data.xml");

cStream = new CryptoStream(readStream,
  RijndaelAlg.CreateDecryptor(RijndaelAlg.Key, RijndaelAlg.IV),
  CryptoStreamMode.Read);

XmlTextReader reader = new XmlTextReader(cStream);

XDocument readContacts = XDocument.Load(reader);

//manipulate with Linq and Save() when needed

Swap your favorite ICryptoTransform into the CryptoStream.

将您最喜欢的ICryptoTransform交换到加密流中。

#2


0  

[update: kudos to Corbin March, who (in the same time) wrote the same, but in code!]

[更新:向Corbin March致敬,他(同时)也写了同样的东西,但是是用代码写的!]

Most streams are one way. I imagine you'd have to:

大多数溪流是一种方式。我想你不得不:

  • create a CryptoStream reading from the (file etc)
  • 创建从(文件等)读取的加密流
  • read the data (for example into XDocument)
  • 读取数据(例如,到XDocument中)
  • do your code (read the document, make changes, etc)
  • 执行您的代码(读取文档,进行更改等)
  • crate a new CryptoStream writing to the (file etc) [starting with the same IV etc)
  • 将一个新的加密流写入(文件等)[以相同的IV等开始)
  • save the docuemnt to the stream
  • 将docuemnt保存到流中

Depending on what the underlying stream is (FileStream, MemoryStream, etc) you may well also have to completely close/re-open it between the read and write (i.e. the CryptoStream will probably feel ownership of the base-stream, and will .Close() it).

根据底层流是什么(FileStream、MemoryStream等),您很可能还必须在读和写之间完全关闭/重新打开它(例如,加密流可能会感到基本流的所有权,并将. close()它)。