Encrypting settings in a config file.

In .NET 2.0/Visual studio 2005 there is a new (and easy) way of keeping application settings. In VS 2005 you can simply enter key-value-type pairs and it will generate code that reads, saves and updates your settings for you. Now with each settingsproperty you can specify whether the property should be saved per user or for all users (application). Lesser known is the option to specify a SettingsProvider class. the specified class will be used for the reading a writing of the property values. As an example I have created a SettingsProvider that wraps the (default) LocalFileSettingsProvider (the one that reads and writes the myApp.exe.config file) and can be applied to string properties.
 
See the inline comment for more information.
 
 class LocalFileEncryptSettingsProvider : LocalFileSettingsProvider
    {
        private string Encrypt(string cleartext)
        {
            string data = cleartext;
 
            // trick to extend the data to a multiple of 16
            // prefix the number of the text’s original length and a ‘#’
            // and append a number ‘$’ to make the multiple of 16
            int length = data.Length;
            data = length.ToString() + “#” + data;
            data = data.PadRight(data.Length + 16 – data.Length % 16, ‘$’);
            // conert to byte array
            byte[] toEncrypt = UnicodeEncoding.Unicode.GetBytes(data);
 
            // Encrypt on a per user base
            ProtectedMemory.Protect(toEncrypt, MemoryProtectionScope.SameLogon);
            // Encode base64 to safely store it in an xml string
            return Convert.ToBase64String(toEncrypt);
        }
 
        private string Decrypt(string encryptedtext)
        {
            string data = encryptedtext;
            byte[] toDecrypt = Convert.FromBase64String(data);
            ProtectedMemory.Unprotect(toDecrypt, MemoryProtectionScope.SameLogon);
            string original = UnicodeEncoding.Unicode.GetString(toDecrypt);
 
            // reverse trick
            int i = original.IndexOf(‘#’);
            int l = int.Parse(original.Substring(0, i));
            return original.Substring(i + 1, l);
        }
 
        public override string Name
        {
            get { return “LocalFileEncryptSettingsProvider”; }
        }
 
        public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
        {
            SettingsPropertyValueCollection result = base.GetPropertyValues(context, properties);
            foreach (SettingsPropertyValue propertyValue in result)
            {
                propertyValue.PropertyValue = Decrypt(propertyValue.PropertyValue.ToString());
            }
            return result;
        }
 
        public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection values)
        {
            foreach (SettingsPropertyValue propertyValue in values)
            {
                propertyValue.PropertyValue = Encrypt(propertyValue.PropertyValue.ToString());
            }
            base.SetPropertyValues(context, values);
        }
    }