Monday, December 29, 2008

How to encrypt/decrypt with passphrase

I was stuck with this when I started using IIS7's AppCmd utility. The utility allows to export and import appication pool configuration, while not having an option to encode/decode identity password. But it was required to store the configuration under the source control system. So I decided to write a simple command-line encoding/decoding utility for a particular section being fetched by regular expression.

I use a symmetric algorithm because key is defined with passphrase for both encoding and decoding operations. Creating key from passphrase is based on hashing. We are required to have keys with fixed length and character sets, thus hashing goes a long way here:
var bytes = Encoding.Unicode.GetBytes(passphrase);
var key = SHA256Managed.Create().ComputeHash(bytes);
var iv = MD5.Create().ComputeHash(bytes);
Key and vector may have different requirements regarding length of byte arrays. For the RijndaelManaged class they are 32 and 16 respectively. Thus I use SHA256 and MD5 algorithms to get keys with the appropriate length.
var alg = SymmetricAlgorithm.Create();
var ms = new MemoryStream();
var buffer = Encoding.Unicode.GetBytes(text);
 
using (var enc = new CryptoStream(
    ms, alg.CreateEncryptor(key, iv),
    CryptoStreamMode.Write
))
{
    enc.Write(buffer, 0, buffer.Length);
}
The code above feeds the entire text to the CryptoStream. For passwords encoding it shouldn't be a perfomance issue. Decoding has quite similar implementation. Rather than using alg.CreateEncryptor it should use alg.CreateDecryptor there.

Additionally I use a couple of extention methods to format byte array to hexadecimal string and vice versa. Here are the entire Encode/Decode methods implementation and the helper methods:

private static string Encode(string text, string passphrase)
{
    var bytes = Encoding.Unicode.GetBytes(passphrase);
    var key = SHA256Managed.Create().ComputeHash(bytes);
    var iv = MD5.Create().ComputeHash(bytes);
 
    var alg = SymmetricAlgorithm.Create();
    var ms = new MemoryStream();
    var buffer = Encoding.Unicode.GetBytes(text);
 
    using(var enc = new CryptoStream(
        ms, alg.CreateEncryptor(key, iv),
        CryptoStreamMode.Write
    )) enc.Write(buffer, 0, buffer.Length);
 
    return ms.ToArray().ToHexString();
}
 
private static string Decode(string text, string passphrase)
{           
    var bytes = Encoding.Unicode.GetBytes(passphrase);
    var key = SHA256Managed.Create().ComputeHash(bytes);
    var iv = MD5.Create().ComputeHash(bytes);
 
    var alg = SymmetricAlgorithm.Create();
    var ms = new MemoryStream();
 
    var buffer = text.ToByteArray();
 
    try
    {
        using (var enc = new CryptoStream(
            ms, alg.CreateDecryptor(key, iv),
            CryptoStreamMode.Write
        )) enc.Write(buffer, 0, buffer.Length);
    }
    catch (Exception)
    {
        Console.Error.WriteLine("Error: wrong passphrase.");
        Environment.Exit(2);
    }
 
    return Encoding.Unicode.GetString(ms.ToArray());
}
...
internal static string ToHexString(this byte[] bytes)
{
    StringBuilder builder = new StringBuilder(3 * bytes.Length);
 
    for (int i = 0; i < bytes.Length; i++)
    {
        builder.AppendFormat("{0:x2}", bytes[i]);
    }
 
    return builder.ToString().ToLowerInvariant();
}
 
internal static byte[] ToByteArray(this string hexString)
{
    byte[] buffer = new byte[hexString.Length / 2];
 
    for (int i = 0; i < hexString.Length; i += 2)
    {
        buffer[i / 2] = byte.Parse(hexString.Substring(i, 2), NumberStyles.HexNumber);
    }
   
    return buffer;
}

Tuesday, December 9, 2008

How to add support for Google Chrome in ASP.NET

Do you like Google Chrome? I do, especially after they amended the section 11.4 of the EULA

Then what about adding browser capabilities for the browser in ASP.NET. It is better not to modify the browser definition files under the  <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers folder since they can be changed in a next .net framework release or service pack. Just add a .browser file to your web project under the App_Browser folder.

 Here is the content of the file:


<browsers>
  <browser id="GoogleChrome" parentID="Safari1Plus">
    <identification>
      <userAgent match="Chrome/(?'version'(?'major'\d+)\.(?'minor'\d+\.\d+).\d+)" />
    </identification>
    <capture>
    </capture>
    <capabilities>
      <capability name="browser"        value="Chrome" />
      <capability name="majorversion"   value="${major}" />
      <capability name="minorversion"   value="${minor}" />
      <capability name="version"        value="${version}" />
    </capabilities>
  </browser>
</browsers>

When I had done it, I found that it appeared a strange behavior. First starting the site in the Chrome made it stick with the Chrome definition for Apple Safari and vise versa.

After playing around with different variations of the above config I decided to stop wasting my time on it and to find how ASP.NET caches the browser capabilities using a reflector. The code of all this is pretty easy. The framework uses the User-Agent request-header as a cache key trimming its length by a configurable parameter.


 
<system.web>
    <browserCaps userAgentCacheKeyLength="128" />

I extended the value up to 128 from its default of 64 because the Chrome's user-agent string length is 118.

 

.net structures performance tips and tricks

Recently I dug into clr structure performance and found it's rather funny. Some revelations were new to me.

At first. If you have a structure containing two boolean fields, it is five times faster than structure containing three boolean fields, but it is equal to four boolean fields one! I merely return structure from method several million times and capture elapsed time by Stopwatcher (it is common scenario when we pass structure to method or return from it):
public struct TestStruct
{
    public bool Field1;
    public bool Field2;
    public bool Field3;
    public bool Field4;

    public static TestStruct CreateNew()
    {
        return default(TestStruct);
    }
}

static void Main(string[] args)
{
    const int iterations = 50000000;
    var sw = Stopwatch.StartNew();

    for (int i = 0; i < iterations; i++)
    {
        var a = TestStruct.CreateNew();
    }

    sw.Stop();
    Console.WriteLine("elapsed {0} ms", sw.ElapsedMilliseconds);
    Console.ReadKey();
}
It seems like it depends on how optimal structure layout is for clr. A boolean field takes one byte. Let's add one more boolean field (fifth). Now we have the five times slump again. But, if we add one more boolean field (sixth), we have the same loss in performance. Seventh such field makes performance seven times slower :).

Conclusionthe optimal structure size values are 1, 2, 4, 8. Let's take a look at another example:


public bool Field1;
public bool Field2;
public bool Field3;
public bool Field4;
public bool Field5;
public short Field6;
public bool Field7;


public short Field1;
public bool Field2;
public bool Field3;
public bool Field4;
public bool Field5;
public bool Field6;
public bool Field7;

The structure fields ordering from the first column four times slower than from the second. It seems it is because Field6 allocation starts from an uneven byte 5. Conclusion: field starting byte should be even if the field takes more than one byte.

The structure from our last example has eight bytes size and it's equal to a single long type allocation in memory. What if we create a 9 bytes size structure. Yes, it would be slowly and it is four times slowly. But the even and uneven allocation rules are still correct and can hit performace in approximately 2 times.

Can we make up more generalize conclusion? I think so. If we create a structure with a single long type field and then will add one more long field and then one more we will see that we have approximately arithmetical progression in growth of elapsed intereval for our loop. Conclusion: the less structure the better. Difference between one and two longs allocation is highest: five times, but then it becomes less and less for 2 vs 3, 3 vs 4 long type fields structures.

Comparing a simple class object creation time with 2 long type fields structure shows that such the structure is still 3 times faster. But a six long type fields structure creation time is approximately equal to that of the class.