Monday, 2 April 2012

Encrypting your settings in your App.config files

I’m currently brushing up on my WCF after my exposure to WSE 3.0 a few years ago. In anticipation of upcoming client work and lack of a TS: WCF Application with the .NET Framework 4 book based material (note it is only course-based), I opted for a good solid book that covered the subject matter in a thorough way.

I opted for WCF 4 Step by Step by John Sharp, as I had purchased the previous WCF book he published a few years ago. I did like his thorough style because I needed to learn it from scratch.

In Chapter 4, “Protecting an Enterprise WCF Service”, he uses some examples where you enter your domain, username and password directly into the code(!). BUT – he does have a warning on every code sample:
Warning: This code is for illustrative purposes in this exercise only. In a production application, you should prompt the user for their name and password. You should never hard-code these details into an application.
Now, I do nearly all of my development on my work laptop. The thought of someone just searching my computer remotely for files with my well-known domain and username puts me off completely. So instead, I decided to apply encryption to it and looked for a way which did not require me to write another program.

Using existing tools to apply the encryption

In the TS: Web Applications with the .NET Framework 4, they discussed how to encrypt the <connectionStrings> section in your web.config. However, I want to leverage this to encrypt my <appSettings> section instead.

First thing, start up a Visual Studio Command Prompt and CD to your location. We want to rename the app.config (prior to the build process) to web.config. For this example, we’ll assume my application in development is at C:\Projects\EncryptConfig directory.
C:\> cd C:\Projects\EncryptConfig
C:\Projects\EncryptConfig> ren app.config web.config
Next is to leverage the encryption utilities in the aspnet_regiis utility. All we provide is the section to encrypt and the file to apply the encryption to:
aspnet_regiis –pef “appSettings” .
The –pef indicates we want to encrypt a specific section and provide the filename. If you have CD’d to the directory, you can just use –pe “appSettings” and it will look for the web.config file.

The next step is to rename the file back to an app.config:
ren web.config app.config
You will notice that the app.config has encrypted this section like this:
<appSettings configProtectionProvider="DataProtectionConfigurationProvider">
   <EncryptedData>
      <CipherData>
         <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAaUZOOb4EQkGNPyy5tzAjBgQAAAACAAAAAAADZgAAwAAAABAAAADQc+YHWZxsOuA55uoTOnvLAAAAAASAAACgAAAAEAAAAPYMaWCQj/hrK3T9DwGH2rxQAQAAyGBicUMztQUL+3cm7QJa5Nxf0NIlHv8WcT7rog67OaMFFc09qVZjmoloAaSsSZMLJC+Xof42NQ1H+x90kOASWvyWibqXkczP7bIy5/9whKb9T0eoHgpnqKu+WmiQQCf7pnM5XIY25TJ1uxzSu+pWZfabLkzfFZah6PaT/fLNCR7DLraewvX7LMmQk2+YLhEot+RDrXAtum7qpCweFFLCS8g8L9tTpz/XzKFjaXJqlJAGru8f9+PgEDOBCVxic8cvzjKizyxSQlS55ht0bJUD1NO6LGOQwtek7SKX2DjOCqQoWGf1uVXePtft73eN+JY7wcCjftu6IWQqUYdj2DMCFn6vZhaNYF5TkHtKv4kpZtNer+s50Yc8E2uUPq99ZZ8vZQMiGdQ8xopIWwx5F/WFUxpeQ5/hG4A4IKhY2njSC3m/efH4M28MWET34HTXVx1gFAAAAGC4o4MxMGI73etkgTMojENDadwS
         </CipherValue>
      </CipherData>
   </EncryptedData>
</appSettings>
The thing to note here is it is using the DataProtectionConfigurationProvider accesses the Data Protection API which is a user-specific API. It is fine as long as you always log in with your user, on your domain. But if you tried to distribute this application, the section would never be able to be read by another computer.

The RSAProtectedConfigurationProvider allows you to encrypt specific to the user or the machine. It also allows you to export the key so that it can be moved to another machine. This would be useful over a web farm (this is an IIS tool after all), where the <machineKey> can be shared across computers.

In any case, if you are looking to distribute this application and encrypt the contents of a configuration file, be sure you understand what encryption methods are available to you.

SyntaxHighlighter - a syntax highlighter for blog posts

I usually use Windows Live Writer to do my blogs. I also have some add-ins to support the syntax highlight, which embeds the CSS into the page.

Today, I viewed the source on my own page, and here is an example of what the "Insert Code Snippet" generated:

// Original formatting with no CSS
Console.WriteLine("Hello World!");
Console.WriteLine("Hello World!");
Console.WriteLine("Hello World!");
Gets rendered to ....


<div id="codeSnippetWrapper">
<br>
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt;
background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%;
padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr;
border-top-style: none; color: black; border-right-style: none; font-size: 8pt;
overflow: visible; padding-top: 0px" id="codeSnippet">
<br />
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt;
background-color: white; margin: 0em; border-left-style: none; padding-left: 0px;
width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace;
direction: ltr; border-top-style: none; color: black; border-right-style: none;
font-size: 8pt; overflow: visible; padding-top: 0px"><br />
<span style="color: #606060" id="lnum1">1:</span><br />
Console.WriteLine(<span style="color: #006080">"Hello World!"</span>);</pre>
<br />
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt;
background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px;
width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace;
direction: ltr; border-top-style: none; color: black; border-right-style: none;
font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060"
id="lnum2">2:</span><br />
Console.WriteLine(<span style="color: #006080">"Hello World!"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt;
background-color: white; margin: 0em; border-left-style: none; padding-left: 0px;
width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace;
direction: ltr; border-top-style: none; color: black; border-right-style: none;
font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060"
id="lnum3">3:</span> <br/>
Console.WriteLine(<span style="color: #006080">"Hello World!"</span>);</pre>
<!--CRLF-->
</div>
</div>
Okay, that is pretty horrific. Does the job, no doubt but when it comes to editing this in the application, it is a complete nightmare. It selects single rows, changes their width accidently. When you have a bit of luck actually selecting the outer div, the Code Snippet editor even warns you that it is going to attempt to read it. When viewing this on a mobile device, it looks even worse. Much worse trust me!

At the same time I was catching up with my Google Reader and was looking through posts I'd missed by Scott Hanselman. He was looking for a syntax highlighter for Windows Live Writer a few years ago. He also went to the trouble of writing a Windows Live Writer plug-in for it. But luckily, things have been made much easier.

How to add SyntaxHighlighter to your site

  1. Download the Javascript and CSS libraries from the SyntaxHighligter authors site. (Alternatively reference them as described)
  2. Add a few lines of script, referencing the code types you wish to use, including the core libraries.
    <script src="shCore.js" type="text/javascript"></script>
    <script src="shAutoloader.js" type="text/javascript"></script>
    <script type="text/javascript">SyntaxHighlighter.autoloader(
    'js jscript javascript /js/shBrushJScript.js',
    'csharp c-sharp /js/shBrushCSharp.js',
    'xml /js/shBrushXml.js'
    );


    SyntaxHighlighter.all();
              http://alexgorbatchev.com/SyntaxHighlighter/manual/api/autoloader.html
In your HTML of your blog post, or site, all you do is add the nice and friendly <pre> tag that we all know and love, applied with a 'class' attribute with your programming language - simples!.

So here is a code sample (from a previous post) and the newer way I will be blogging from now on:

Before


   1: # PowerShell script to modify the 'timeout' value in the specified web.config    
   2: # when no Sessions are in use.    
   3:  
   4: # Constants used throughout application    
   5: $webConfig = "d:\web.config"    
   6: $newTimeout = "20"    
   7: $sessionCount = 0    
   8:  
   9: ## BEGIN   
  10: write-host Getting performance counters ...   
  11:  
  12: $perfCounterString = "\asp.net applications(__total__)\sessions total"    
  13: $perfCounter = get-counter -counter $perfCounterString    
  14: $rawValue = $perfCounter .CounterSamples[0].CookedValue    
  15:  
  16: write-host Session Count is $rawValue   
  17:  
  18: if( $rawValue -gt $sessionCount)   
  19: {   
  20:    write-host Session Count = $rawValue - exiting   
  21:    exit   
  22: }   
  23:  
  24: write-host Stopping IIS   
  25: stop-service "IISAdmin"   
  26:  
  27: # Open file and change value   
  28: $doc = new-object System.Xml.XmlDocument   
  29: $doc.Load($webConfig)   
  30: $doc.SelectSingleNode("//sessionState").timeout = $newTimeout    
  31: $doc.Save($webConfig)   
  32:  
  33: write-host Starting IIS   
  34: start-service "IISAdmin"   
  35:  
  36: write-host Done!   
  37: ## END

After


# PowerShell script to modify the 'timeout' value in the specified web.config    
# when no Sessions are in use.

# Constants used throughout application
$webConfig = "d:\web.config"
$newTimeout = "20"
$sessionCount = 0

## BEGIN
write-host Getting performance counters ...
$perfCounterString = "\asp.net applications(__total__)\sessions total"
$perfCounter = get-counter -counter $perfCounterString
$rawValue = $perfCounter .CounterSamples[0].CookedValue

write-host Session Count is $rawValue

if( $rawValue -gt $sessionCount)
{
write-host Session Count = $rawValue - exiting
exit
}

write-host Stopping IIS
stop-service "IISAdmin"

# Open file and change value
$doc = new-object System.Xml.XmlDocument
$doc.Load($webConfig)
$doc.SelectSingleNode("//sessionState").timeout = $newTimeout
$doc.Save($webConfig)

write-host Starting IIS
start-service "IISAdmin"
write-host Done!
## END

Have a look at the source of this page to see how readable each section is.