سؤال

I want to use encrypted xml file as application resource for easy xaml data binding. Xml file are encrypted in different application. I can use unencrypted xml for data binding. I cant use the same method for encrypted xml because the file is encrypted when it is loaded. I have to decrypt it first before it can be use. Problem is, where do I put decryption algorithm?

Here how i create the encrypted files(code for decrypt and verifying decrypted data are omitted)

            RijndaelManaged algorithm = null;

            algorithm = new RijndaelManaged();
            string passwordBytes = "password"; //password here
            byte[] saltBytes = Encoding.UTF8.GetBytes("salt"); // salt here (another string)
            var p = new Rfc2898DeriveBytes(passwordBytes, saltBytes);
            algorithm.IV = p.GetBytes(algorithm.BlockSize / 8);
            algorithm.Key = p.GetBytes(algorithm.KeySize / 8);

            var xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("Bands.xml");

            // Encrypt the "Bands" element.
            Encrypt(xmlDoc, "Bands", algorithm);
            xmlDoc.Save("encryptedBands.xml");

To decrypt, i just call these(assuming xmlDoc and algorithm are same as above.

Decrypt(xmlDoc, algorithm);

Here are encrypt and decrypt algorithm based on msdn(nothing special).

        public static void Encrypt(XmlDocument Doc, string ElementName, SymmetricAlgorithm Key)
    {
        // Check the arguments.   
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (ElementName == null)
            throw new ArgumentNullException("ElementToEncrypt");
        if (Key == null)
            throw new ArgumentNullException("Alg");

        var elementToEncrypt = Doc.GetElementsByTagName(ElementName)[0] as XmlElement;
        // Throw an XmlException if the element was not found. 
        if (elementToEncrypt == null)
        {
            throw new XmlException("The specified element was not found");

        }

        var eXml = new EncryptedXml();

        byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);

        var edElement = new EncryptedData();
        edElement.Type = EncryptedXml.XmlEncElementUrl;

        string encryptionMethod = null;

        if (Key is TripleDES)
        {
            encryptionMethod = EncryptedXml.XmlEncTripleDESUrl;
        }
        else if (Key is DES)
        {
            encryptionMethod = EncryptedXml.XmlEncDESUrl;
        }
        if (Key is Rijndael)
        {
            switch (Key.KeySize)
            {
                case 128:
                    encryptionMethod = EncryptedXml.XmlEncAES128Url;
                    break;
                case 192:
                    encryptionMethod = EncryptedXml.XmlEncAES192Url;
                    break;
                case 256:
                    encryptionMethod = EncryptedXml.XmlEncAES256Url;
                    break;
            }
        }
        else
        {
            // Throw an exception if the transform is not in the previous categories 
            throw new CryptographicException("The specified algorithm is not supported for XML Encryption.");
        }

        edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);

        // Add the encrypted element data to the  
        // EncryptedData object.
        edElement.CipherData.CipherValue = encryptedElement;
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    }

    public static void Decrypt(XmlDocument Doc, SymmetricAlgorithm Alg)
    {
        // Check the arguments.   
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (Alg == null)
            throw new ArgumentNullException("Alg");

        // Find the EncryptedData element in the XmlDocument.
        var encryptedElement = Doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;

        // If the EncryptedData element was not found, throw an exception. 
        if (encryptedElement == null)
        {
            throw new XmlException("The EncryptedData element was not found.");
        }


        // Create an EncryptedData object and populate it.
        var edElement = new EncryptedData();
        edElement.LoadXml(encryptedElement);

        // Create a new EncryptedXml object.
        var exml = new EncryptedXml();


        // Decrypt the element using the symmetric key. 
        byte[] rgbOutput = exml.DecryptData(edElement, Alg);

        // Replace the encryptedData element with the plaintext XML element.
        exml.ReplaceData(encryptedElement, rgbOutput);

    }

I want to use the encrypted xml data as data source for easy data binding in xaml. I declare xml data at application level for application wide access. Here's how I declared it in App.xaml.

    <Application.Resources>
    <ResourceDictionary>
        <XmlDataProvider x:Key="encryptedBandsDataSource" Source="/RemoteConfigurator;component/encryptedBands.xml" d:IsDataSource="True"/>
    </ResourceDictionary>
</Application.Resources>

Problem is, I need to decrypt the xml file before App.xaml is even loaded. Is it possible to do that. How do I do that. Where do I decrypt the xml file?

In short, how can I use encrypted xml file as application resources?

هل كانت مفيدة؟

المحلول

Two options, a quick one and a clean one...

Option 1 (quick): Decrypt file before loading the app

If you decrypt your file, before base.OnStartup(e) is called in app.xaml.cs, it should work...

using System.Windows;

namespace MainApplication
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            DecryptXml();
            base.OnStartup(e);

            MainBootstrapper bootstrapper = new MainBootstrapper();
            bootstrapper.Run();
        }
    }

}

Option 2 (clean): Custom XmlDataProvider to handle encrypted XML files

Another option is to write a custom XmlDataProvider, say EncryptedXmlDataProvider, which holds an EncryptedSource property and some other properties to specify how to decrypt the file. EncryptedXmlDataProvider can decrypt the file, when EncryptedSource property is set. This way, the Data is blendable and you have a reusable type. A bit more work but much cleaner than the solution proposed above.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top