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

TripleDES Encrypted Configuration File

By , 29 Feb 2004
 

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

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

About the Author

Matthew Hazlett
Web Developer
United States United States
Member
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.
 


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalpublic key reference in your articlesussSteve Bansleben25 Aug '04 - 8:58 
Matthew,
 
It is very confusing to mention the word public in your article about a 'private' symmetric key encryption method such as TripleDES. This should be reserved for PKI discussions.
 
Steve Bansleben
GeneralDon't .xml file extension!memberJimHugh1 Mar '04 - 2:37 
*.xml files are not processed by the aspnet_filter.dll and a result can be freely downloaded (depending on NTFS security).
 
Use a "protected" file extension like .config for your settings file to prevent your settings file from being downloaded!
 
Jim Hughes
GeneralRe: Don't .xml file extension!memberMatthew Hazlett1 Mar '04 - 8:17 
Damn, didn't even think about this!
I'll post another update soon, thanks for the great idea!
 

 
Matthew Hazlett
Windows 2000/2003 MCSE
Never got an MCSD, go figure...
GeneralRe: Don't .xml file extension!memberMatthew Hazlett1 Mar '04 - 9:33 
Fixed and posted, thanks again.

 
Matthew Hazlett
Windows 2000/2003 MCSE
Never got an MCSD, go figure...
GeneralHave a lookmemberMrEyes1 Mar '04 - 0:32 
Nice project, and nice idea.
 
You might want to have a look at this :
 
http://www.obviex.com/CipherLite/
 

 
post.mode = signature;
SELECT everything FROM everywhere WHERE something = something_else;
> 1 Row Returned
> 42
GeneralBetter to use DPAPImemberisraeli029 Feb '04 - 19:40 
Your class suffers of one big weakness and it is the private key which is stored in the code, this key can be viewed with simple reflection or even just by looking at your code with ildasm.
 
It's better to use DPAPI as you wont have to deal with keys maintenance.
 
Check CMAB – Ready made MS Application block made just for that purpose.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/cmab.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/windataprotection-dpapi.asp

GeneralRe: Better to use DPAPImemberMatthew Hazlett29 Feb '04 - 20:06 
Thanks, I just noticed this myself. I will definitly look into this and post an update.
Thanks again.
 
Matthew Hazlett
Windows 2000/2003 MCSE
Never got an MCSD, go figure...
GeneralRe: Better to use DPAPImemberMatthew Hazlett29 Feb '04 - 20:32 
Thanks again for the heads up. The code and demos have been updated. All I had to do was change how the variable was declared. An its alot simpler then Application Block, I'm still looking at it (looks very complex at first glance).
 

Matthew Hazlett
Windows 2000/2003 MCSE
Never got an MCSD, go figure...
GeneralRe: Better to use DPAPImemberRichard Deeming10 Mar '04 - 6: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 DPAPImemberMatthew Hazlett10 Mar '04 - 7:15 

You will need to restrict the read permission on the file to make it more secure. As with any code you can always go in and find what you need to circumvent security.

 
Matthew Hazlett
Windows 2000/2003 MCSE
Never got an MCSD, go figure...

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

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