none
How can I protect a server credetials stored in App.config? RRS feed

  • Question

  • Hi, I have implemented two components, Client and Server, where the former connects in SSH to the latter through Renci.SSH.

    The Server credentials useful for connection through the SftpClient constructor

    SftpClient client = new SftpClient(serverIP, serverPort, serverName, serverPassword);

    client.Connect();

    //...

    are stored in the Client configuration file (App.Config), in order to not insert them statically in the code. Those credentials are in the AppSettings section of the App.Config:

    <appSettings>

    ...

    <add key="SERVER IP" value="xx.xx.xx.xx"/> <add key="SERVER PORT" value="22"/> <add key="SERVER USERNAME" value="Username"/> <add key="SERVER PASSWORD" value="Password"/>

    ...

    </appSettings>


    and they are retrieved through the ConfigurationManager class. But those credetials are unencrypted and this is a problem. 

    The AppSettings section contains other app settings that can stay unenctypted!

    How can I protect/encrypt those appsettings (SERVER IP, SERVER PORT, SERVER USERNAME, SERVER PASSWORD) in my App.Config file? 


    Monday, February 24, 2020 1:34 PM

Answers

  • If you stored the information as a connection string you could use EncryptFile and DecryptFile methods and IsProtected method to determine if encrypted. Downside is you can't change the connection string later unless you rerun EncryptFile on an unencrypted file.

    using System;
    using System.Configuration;
    using System.IO;
    
    namespace ConfigurationLibrary 
    {
        public class ConnectionProtection
        {
            public string FileName { get; set; }
            public ConnectionProtection(string ExecutableFileName)
            {
                if (!(File.Exists(string.Concat(ExecutableFileName, ".config"))))
                {
                    throw new FileNotFoundException(string.Concat(ExecutableFileName, ".config"));
                }
                FileName = ExecutableFileName;
            }
            private bool EncryptConnectionString(bool encrypt, string fileName)
            {
                bool success = true;
                Configuration configuration = null;
    
                try
                {
                    configuration = ConfigurationManager.OpenExeConfiguration(fileName);
                    var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
    
                    if ((!configSection.ElementInformation.IsLocked) && (!configSection.SectionInformation.IsLocked))
                    {
                        if (encrypt && (!configSection.SectionInformation.IsProtected))
                        {
                            // encrypt the file
                            configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                        }
    
                        if ((!encrypt) && configSection.SectionInformation.IsProtected) //encrypt is true so encrypt
                        {
                            // decrypt the file. 
                            configSection.SectionInformation.UnprotectSection();
                        }
    
                        configSection.SectionInformation.ForceSave = true;
                        configuration.Save();
    
                        success = true;
    
                    }
                }
                catch (Exception)
                {
                    success = false;
                }
    
                return success;
    
            }
            public bool IsProtected()
            {
                var configuration = ConfigurationManager.OpenExeConfiguration(FileName);
                var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                return configSection.SectionInformation.IsProtected;
            }
            public bool EncryptFile() => File.Exists(FileName) && EncryptConnectionString(true, FileName);
    
            public bool DecryptFile() => File.Exists(FileName) && EncryptConnectionString(false, FileName);
        }
    }
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, February 24, 2020 1:43 PM
    Moderator
  • If you stored the information as a connection string you could use EncryptFile and DecryptFile methods and IsProtected method to determine if encrypted. Downside is you can't change the connection string later unless you rerun EncryptFile on an unencrypted file.

    using System;
    using System.Configuration;
    using System.IO;
    
    namespace ConfigurationLibrary 
    {
        public class ConnectionProtection
        {
            public string FileName { get; set; }
            public ConnectionProtection(string ExecutableFileName)
            {
                if (!(File.Exists(string.Concat(ExecutableFileName, ".config"))))
                {
                    throw new FileNotFoundException(string.Concat(ExecutableFileName, ".config"));
                }
                FileName = ExecutableFileName;
            }
            private bool EncryptConnectionString(bool encrypt, string fileName)
            {
                bool success = true;
                Configuration configuration = null;
    
                try
                {
                    configuration = ConfigurationManager.OpenExeConfiguration(fileName);
                    var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
    
                    if ((!configSection.ElementInformation.IsLocked) && (!configSection.SectionInformation.IsLocked))
                    {
                        if (encrypt && (!configSection.SectionInformation.IsProtected))
                        {
                            // encrypt the file
                            configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                        }
    
                        if ((!encrypt) && configSection.SectionInformation.IsProtected) //encrypt is true so encrypt
                        {
                            // decrypt the file. 
                            configSection.SectionInformation.UnprotectSection();
                        }
    
                        configSection.SectionInformation.ForceSave = true;
                        configuration.Save();
    
                        success = true;
    
                    }
                }
                catch (Exception)
                {
                    success = false;
                }
    
                return success;
    
            }
            public bool IsProtected()
            {
                var configuration = ConfigurationManager.OpenExeConfiguration(FileName);
                var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                return configSection.SectionInformation.IsProtected;
            }
            public bool EncryptFile() => File.Exists(FileName) && EncryptConnectionString(true, FileName);
    
            public bool DecryptFile() => File.Exists(FileName) && EncryptConnectionString(false, FileName);
        }
    }


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    There is a method to do that with the appsettings too, instead of using connectionstrings?

    See the following

    https://weblogs.asp.net/jongalloway/encrypting-passwords-in-a-net-app-config-file


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    The solution is right. But I can change 
    var configSection = configuration.GetSection("appSettings") as AppSettingsSection;
    and it worked! Thank you
    Monday, February 24, 2020 2:43 PM

All replies

  • If you stored the information as a connection string you could use EncryptFile and DecryptFile methods and IsProtected method to determine if encrypted. Downside is you can't change the connection string later unless you rerun EncryptFile on an unencrypted file.

    using System;
    using System.Configuration;
    using System.IO;
    
    namespace ConfigurationLibrary 
    {
        public class ConnectionProtection
        {
            public string FileName { get; set; }
            public ConnectionProtection(string ExecutableFileName)
            {
                if (!(File.Exists(string.Concat(ExecutableFileName, ".config"))))
                {
                    throw new FileNotFoundException(string.Concat(ExecutableFileName, ".config"));
                }
                FileName = ExecutableFileName;
            }
            private bool EncryptConnectionString(bool encrypt, string fileName)
            {
                bool success = true;
                Configuration configuration = null;
    
                try
                {
                    configuration = ConfigurationManager.OpenExeConfiguration(fileName);
                    var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
    
                    if ((!configSection.ElementInformation.IsLocked) && (!configSection.SectionInformation.IsLocked))
                    {
                        if (encrypt && (!configSection.SectionInformation.IsProtected))
                        {
                            // encrypt the file
                            configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                        }
    
                        if ((!encrypt) && configSection.SectionInformation.IsProtected) //encrypt is true so encrypt
                        {
                            // decrypt the file. 
                            configSection.SectionInformation.UnprotectSection();
                        }
    
                        configSection.SectionInformation.ForceSave = true;
                        configuration.Save();
    
                        success = true;
    
                    }
                }
                catch (Exception)
                {
                    success = false;
                }
    
                return success;
    
            }
            public bool IsProtected()
            {
                var configuration = ConfigurationManager.OpenExeConfiguration(FileName);
                var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                return configSection.SectionInformation.IsProtected;
            }
            public bool EncryptFile() => File.Exists(FileName) && EncryptConnectionString(true, FileName);
    
            public bool DecryptFile() => File.Exists(FileName) && EncryptConnectionString(false, FileName);
        }
    }
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, February 24, 2020 1:43 PM
    Moderator
  • If you stored the information as a connection string you could use EncryptFile and DecryptFile methods and IsProtected method to determine if encrypted. Downside is you can't change the connection string later unless you rerun EncryptFile on an unencrypted file.

    using System;
    using System.Configuration;
    using System.IO;
    
    namespace ConfigurationLibrary 
    {
        public class ConnectionProtection
        {
            public string FileName { get; set; }
            public ConnectionProtection(string ExecutableFileName)
            {
                if (!(File.Exists(string.Concat(ExecutableFileName, ".config"))))
                {
                    throw new FileNotFoundException(string.Concat(ExecutableFileName, ".config"));
                }
                FileName = ExecutableFileName;
            }
            private bool EncryptConnectionString(bool encrypt, string fileName)
            {
                bool success = true;
                Configuration configuration = null;
    
                try
                {
                    configuration = ConfigurationManager.OpenExeConfiguration(fileName);
                    var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
    
                    if ((!configSection.ElementInformation.IsLocked) && (!configSection.SectionInformation.IsLocked))
                    {
                        if (encrypt && (!configSection.SectionInformation.IsProtected))
                        {
                            // encrypt the file
                            configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                        }
    
                        if ((!encrypt) && configSection.SectionInformation.IsProtected) //encrypt is true so encrypt
                        {
                            // decrypt the file. 
                            configSection.SectionInformation.UnprotectSection();
                        }
    
                        configSection.SectionInformation.ForceSave = true;
                        configuration.Save();
    
                        success = true;
    
                    }
                }
                catch (Exception)
                {
                    success = false;
                }
    
                return success;
    
            }
            public bool IsProtected()
            {
                var configuration = ConfigurationManager.OpenExeConfiguration(FileName);
                var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                return configSection.SectionInformation.IsProtected;
            }
            public bool EncryptFile() => File.Exists(FileName) && EncryptConnectionString(true, FileName);
    
            public bool DecryptFile() => File.Exists(FileName) && EncryptConnectionString(false, FileName);
        }
    }


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    There is a method to do that with the appsettings too, instead of using connectionstrings?
    Monday, February 24, 2020 1:51 PM
  • If you stored the information as a connection string you could use EncryptFile and DecryptFile methods and IsProtected method to determine if encrypted. Downside is you can't change the connection string later unless you rerun EncryptFile on an unencrypted file.

    using System;
    using System.Configuration;
    using System.IO;
    
    namespace ConfigurationLibrary 
    {
        public class ConnectionProtection
        {
            public string FileName { get; set; }
            public ConnectionProtection(string ExecutableFileName)
            {
                if (!(File.Exists(string.Concat(ExecutableFileName, ".config"))))
                {
                    throw new FileNotFoundException(string.Concat(ExecutableFileName, ".config"));
                }
                FileName = ExecutableFileName;
            }
            private bool EncryptConnectionString(bool encrypt, string fileName)
            {
                bool success = true;
                Configuration configuration = null;
    
                try
                {
                    configuration = ConfigurationManager.OpenExeConfiguration(fileName);
                    var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
    
                    if ((!configSection.ElementInformation.IsLocked) && (!configSection.SectionInformation.IsLocked))
                    {
                        if (encrypt && (!configSection.SectionInformation.IsProtected))
                        {
                            // encrypt the file
                            configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                        }
    
                        if ((!encrypt) && configSection.SectionInformation.IsProtected) //encrypt is true so encrypt
                        {
                            // decrypt the file. 
                            configSection.SectionInformation.UnprotectSection();
                        }
    
                        configSection.SectionInformation.ForceSave = true;
                        configuration.Save();
    
                        success = true;
    
                    }
                }
                catch (Exception)
                {
                    success = false;
                }
    
                return success;
    
            }
            public bool IsProtected()
            {
                var configuration = ConfigurationManager.OpenExeConfiguration(FileName);
                var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                return configSection.SectionInformation.IsProtected;
            }
            public bool EncryptFile() => File.Exists(FileName) && EncryptConnectionString(true, FileName);
    
            public bool DecryptFile() => File.Exists(FileName) && EncryptConnectionString(false, FileName);
        }
    }


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    There is a method to do that with the appsettings too, instead of using connectionstrings?

    See the following

    https://weblogs.asp.net/jongalloway/encrypting-passwords-in-a-net-app-config-file


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, February 24, 2020 2:10 PM
    Moderator
  • If you stored the information as a connection string you could use EncryptFile and DecryptFile methods and IsProtected method to determine if encrypted. Downside is you can't change the connection string later unless you rerun EncryptFile on an unencrypted file.

    using System;
    using System.Configuration;
    using System.IO;
    
    namespace ConfigurationLibrary 
    {
        public class ConnectionProtection
        {
            public string FileName { get; set; }
            public ConnectionProtection(string ExecutableFileName)
            {
                if (!(File.Exists(string.Concat(ExecutableFileName, ".config"))))
                {
                    throw new FileNotFoundException(string.Concat(ExecutableFileName, ".config"));
                }
                FileName = ExecutableFileName;
            }
            private bool EncryptConnectionString(bool encrypt, string fileName)
            {
                bool success = true;
                Configuration configuration = null;
    
                try
                {
                    configuration = ConfigurationManager.OpenExeConfiguration(fileName);
                    var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
    
                    if ((!configSection.ElementInformation.IsLocked) && (!configSection.SectionInformation.IsLocked))
                    {
                        if (encrypt && (!configSection.SectionInformation.IsProtected))
                        {
                            // encrypt the file
                            configSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                        }
    
                        if ((!encrypt) && configSection.SectionInformation.IsProtected) //encrypt is true so encrypt
                        {
                            // decrypt the file. 
                            configSection.SectionInformation.UnprotectSection();
                        }
    
                        configSection.SectionInformation.ForceSave = true;
                        configuration.Save();
    
                        success = true;
    
                    }
                }
                catch (Exception)
                {
                    success = false;
                }
    
                return success;
    
            }
            public bool IsProtected()
            {
                var configuration = ConfigurationManager.OpenExeConfiguration(FileName);
                var configSection = configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                return configSection.SectionInformation.IsProtected;
            }
            public bool EncryptFile() => File.Exists(FileName) && EncryptConnectionString(true, FileName);
    
            public bool DecryptFile() => File.Exists(FileName) && EncryptConnectionString(false, FileName);
        }
    }


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    There is a method to do that with the appsettings too, instead of using connectionstrings?

    See the following

    https://weblogs.asp.net/jongalloway/encrypting-passwords-in-a-net-app-config-file


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    The solution is right. But I can change 
    var configSection = configuration.GetSection("appSettings") as AppSettingsSection;
    and it worked! Thank you
    Monday, February 24, 2020 2:43 PM

  • profile for Karen Payne on Stack Exchange


    But which Crypt algorithm is used to do that? 
    Monday, February 24, 2020 2:46 PM
  • Here is all I have time to invest here. The code below came from the last link and placed into a class.

    using System;
    using System.Security;
    
    // Install-Package System.Security.Cryptography.ProtectedData -Version 4.7.0
    using System.Security.Cryptography; 
    
    using System.Text;
    
    namespace SecureConnection
    {
        /// <summary>
        /// Original source https://weblogs.asp.net/jongalloway/encrypting-passwords-in-a-net-app-config-file
        /// </summary>
        public class ConfigSecurity
        {
            private static readonly byte[] entropy = Encoding.Unicode.GetBytes("Well thank you for saying that");
    
            public static string EncryptString(SecureString input)
            {
    
                byte[] encryptedData = ProtectedData.Protect(
                    Encoding.Unicode.GetBytes(ToInsecureString(input)), 
                    entropy, 
                    DataProtectionScope.CurrentUser);
    
                return Convert.ToBase64String(encryptedData);
            }
    
            public static SecureString DecryptString(string encryptedData)
            {
                try
                {
                    byte[] decryptedData = ProtectedData.Unprotect(
                        Convert.FromBase64String(encryptedData), 
                        entropy, 
                        DataProtectionScope.CurrentUser);
    
                    return ToSecureString(Encoding.Unicode.GetString(decryptedData));
                }
                catch
                {
                    return new SecureString();
                }
            }
    
            public static SecureString ToSecureString(string input)
            {
                var secure = new SecureString();
                foreach (var character in input)
                {
                    secure.AppendChar(character);
                }
    
                secure.MakeReadOnly();
    
                return secure;
    
            }
    
            public static string ToInsecureString(SecureString input)
            {
                string returnValue = string.Empty;
                IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
    
                try
                {
                    returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
                }
                finally
                {
                    System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
                }
    
                return returnValue;
            }
        }
    }
    

    Here is enough to get you going.

    var value = AppSettings["SERVER PORT"];
    var result = ConfigSecurity.EncryptString(ConfigSecurity.ToSecureString(value));
    
    Console.WriteLine(result);
    var unSecure = ConfigSecurity.DecryptString(result);
    Console.WriteLine(ConfigSecurity.ToInsecureString(unSecure));

    Output

    AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAlnv2Xv+1QkOe0VsWWwM/rgAAAAACAAAAAAADZgAAwAAAABAAAAAvMYdnxE4YsqGItXmZEn7aAAAAAASAAACgAAAAEAAAAG2v+dtWjM/Y6+4fQb10dJYIAAAAV0e3CN3kh5kUAAAAoQvjiiqtG8rIzE2mUN1ORGzQYyk=
    22


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, February 24, 2020 2:53 PM
    Moderator