views:

2364

answers:

2

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?

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.

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.

+6  A: 

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 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.

Corbin March
I tried this with the AesManaged class to do the encryption, and it error because it wanted to have read/write access to the stream. Hmm... I'll try it again. Thanks.
Chris Pietschmann
A: 

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

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)
  • do your code (read the document, make changes, etc)
  • crate a new CryptoStream writing to the (file etc) [starting with the same IV etc)
  • save the docuemnt to the stream

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

Marc Gravell