Click here to Skip to main content
Click here to Skip to main content

TripleDES Encrypted Configuration File

, 29 Feb 2004
Rate this:
Please Sign up or sign in to vote.
How to make your server settings safer

Sample Image - screenshot.png

Introduction

I didn't want plain text configuration files for my production SQL server, I wanted those blocks encrypted with TripleDES. So, what I decided to do was create a class that could read and write configuration files with both plain and encrypted text. (For use in an ASP.NET app).

Updates

2/29/04:
A security hole has been patched where you could see the Private key code using a reflection utility. Now, you can still see the variable decleration but you can not see its value. The source code and demo projects have been updated.

3/1/04:
A security fix to the file names extention was made to prevent the settings.config file from being downloaded. I have also included batch files for commandline compileing.

Problems with security

The only drawback (or good point, depending how you look at it) is that to change the private key the source code has to be changed and recompiled. All the encrypted items that are written out by the program have their own unique public key for maximum security. Lets look at a file:

<appSettings>
  <add key="ownersName" value="Matthew" />
  <add key="emailServer" value="FRAGPDC" />
  <add key="sqlServer" value="FRAGPDC" />
  <add key="sqlUser" encode="90lIn5/qBsY=" value="Dk3fxrNRfvM=" />
  <add key="sqlPassword" encode="YRG9vvfk9m0=" 
       value="SrczFf67nLlL0XgJjfm3gQ==" />
</appSettings>

As you can see not every line is encrypted only the ones that require extra security are encrypted TripleDES. On the lines that are encrypted the [encode] attribute is the public key for that item. The private key is safely tucked away in the compiled DLL.

Reading the data

It is very easy to Read or Display the data using the getSetting method.

Configure.getSetting(key);

key is the name of the key you want from the settings file. If there is no key by that name in the settings file then an empty string will be returned.

Writing the data

Its just as easy to write the data, all you need to do is use the writeSetting method.

Write an encrypted string:
Configure.writeSetting(thisKey, Request.Form[thisKey], true);


Write a text string:
Configure.writeSetting(thisKey, Request.Form[thisKey], false);

thisKey is the name of the key, Request.Form[thisKey] is the value of the key and the true or false is if you want encryption.

Changing the private key

I have included a program that when run will generate a new random key. Here is some sample output:

Next you need to change this line in the source code:

Code

The code in the keyGeneration app is very much similar to the code in the DLL so lets take a look at it. First we have to tell the app what classes we want to use. The System.Text class will provide character encoding services and System.Security.Cryptography is where the algorithms for the encryption are stored.

using System;
using System.Text;

using System.Security.Cryptography;


class MainClass
{
    public static TripleDESCryptoServiceProvider des = 
                                     new TripleDESCryptoServiceProvider(); 

Tto encode and decode the string we have two functions:

    private static string encode(string thisEncode)
    {
        string encrypted;
        byte[] Code = ASCIIEncoding.ASCII.GetBytes(thisEncode);
        
        encrypted = Convert.ToBase64String(
                des.CreateEncryptor().TransformFinalBlock(Code, 0, 
                                                          Code.Length)
      );
        
        return encrypted;
    }


    private static string decode(string thisDecode)
    {
        string decrypted;
        byte[] Code = Convert.FromBase64String(thisDecode);
        
        decrypted = ASCIIEncoding.ASCII.GetString(
                des.CreateDecryptor().TransformFinalBlock(Code, 0, 
                                                          Code.Length)
      );

        return decrypted;
    }

Here is the main block of code to tie it together:

    public static void Main(string[] args)
    {
        des.GenerateIV();
        des.GenerateKey();
                
        Console.WriteLine("New Key");
        Console.WriteLine("You only need to cut and paste the private key " +
                          "into the source");
        Console.WriteLine();
        
        Console.WriteLine(" Public: {0}", Convert.ToBase64String(des.IV));
        Console.WriteLine("Private: {0}", Convert.ToBase64String(des.Key));
        Console.WriteLine();

        string encoded = encode("[Triple DES] This is an encoded string");
        
        Console.WriteLine("Encoded: {0}", encoded);
        Console.WriteLine("Decoded: {0}", decode(encoded));
        Console.WriteLine();
        Console.Write("Press return to exit...");
        Console.ReadLine();
    }

The web Page

Basically this is just a standard aspx web page that imports the namespace of the dll and gathers its information on the PostBack event.

<%@ Page language="c#" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="appSettings.Settings" %>

<script runat="server">
        private void Page_Load(object sender, System.EventArgs e)
        {
            if (this.IsPostBack) 
            {
                foreach (string thisKey in Request.Form.AllKeys) 
                {
                    if (thisKey != "__VIEWSTATE") 
                        if ((thisKey == "databasePassword") || 
                            (thisKey == "databaseUser"))
                        {
                            Configure.writeSetting(thisKey, 
                                                Request.Form[thisKey], true);
                        }
                        else
                        {
                            Configure.writeSetting(thisKey, 
                                                Request.Form[thisKey], false);
                        }
                }
            }
        }
</script>

<HTML>
    <HEAD>
        <title>Setup</title>
        <link rel="stylesheet" type="text/css" href="setup.css" />
    </HEAD>
    <body>
        <form id="appSettings" method="post" runat="server">
        <div id="content">
            <div class="title">Database Server Settings<hr></div>

            <div class="smallTab" id="text">Database Server:</div>
            <div class="bigTab"><input type=text name="databaseServer" 
                    value="<%= Configure.getSetting("databaseServer") %>" 
                  size=30></div>

            <div class="smallTab" id="text">Database User:</div>
            <div class="bigTab"><input type=text name="databaseUser" 
                    value="<%= Configure.getSetting("databaseUser") %>" 
                  size=30></div>

            <div class="smallTab" id="text">Database Name:</div>
            <div class="bigTab"><input type=text name="databaseName" 
                    value="<%= Configure.getSetting("databaseName") %>"  
                  size=30></div>

            <div class="smallTab" id="text">Database Password:</div>
            <div class="bigTab"><input type=password name="databasePassword" 
                    value="<%= Configure.getSetting("databasePassword") %>"  
                  size=30></div>

            <div align="center"><input type="submit" value=" Update Database 
                   Settings "></div>
        </div>
        </form>
    </body>
</HTML>

To install the web page just uncompress the configure_demo.zip into an empty directory under the wwwroot tree.
IMPORTANT: Don't forget to go into the internet control panel and set this directory as an application otherwise the DLL won't be found!

Permissions

For security reasons I didn't write this to the web.config file, its written to settings.config. Now if the ASPNET service (Who your webserver runs as) creates this file the permissions will be fine. But if you create this file you will need to give the ASPNET user access to write to the file. Also if you go in and edit the file later by hand you will need to reset the permissions. You have been warned Smile | :)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Matthew Hazlett
Web Developer
United States United States
I started programming for fun when I was about 10 on an Franklin Ace 1000.
 
I still do it just for fun but it has gotten me a few jobs over the years. More then I can say for my Microsoft Certifications. Smile | :)
 
The way I learned was by example, now its time to give back to the next generation of coders.
 


Comments and Discussions

 
Generalpublic key reference in your article PinsussSteve Bansleben25-Aug-04 9:58 
GeneralDon't .xml file extension! PinmemberJimHugh1-Mar-04 3:37 
GeneralRe: Don't .xml file extension! PinmemberMatthew Hazlett1-Mar-04 9:17 
GeneralRe: Don't .xml file extension! PinmemberMatthew Hazlett1-Mar-04 10:33 
GeneralHave a look PinmemberMrEyes1-Mar-04 1:32 
GeneralBetter to use DPAPI Pinmemberisraeli029-Feb-04 20:40 
GeneralRe: Better to use DPAPI PinmemberMatthew Hazlett29-Feb-04 21:06 
GeneralRe: Better to use DPAPI PinmemberMatthew Hazlett29-Feb-04 21:32 
GeneralRe: Better to use DPAPI PinmemberRichard Deeming10-Mar-04 7:44 
The problem is still there - the string has just moved to the static constructor. Load up the library in ildasm / Reflector[^] / etc, and look for the .cctor method:
ILDASM:
.method private hidebysig specialname rtspecialname static void  .cctor() cil managed
{
    // Code size       21 (0x15)
    .maxstack  1
    IL_0000:  ldstr      "XUenPktGV8KqWFr6RfE2r0Uljn/yV2i0"
    IL_0005:  stsfld     string appSettings.Settings.Configure::privateKey
    IL_000a:  newobj     ...
 
Reflector:
private static Configure()
{
    Configure.privateKey = "XUenPktGV8KqWFr6RfE2r0Uljn/yV2i0";
    Configure.des = new TripleDESCryptoServiceProvider();
}

 

"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
GeneralRe: Better to use DPAPI PinmemberMatthew Hazlett10-Mar-04 8:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 1 Mar 2004
Article Copyright 2004 by Matthew Hazlett
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid