Monday, July 28, 2008

Secure/Encrypted cookies in ASP.NET with System.Cryptography

In today's world one cant transmit a digital syllable without some kind of protective wrapper around it. Us Neos of the binary world have always struggled with proper cipher methods to do so.

In other words, beginners always have had difficulty in implementing a reliable yet flexible method for securing cookies. I have used the following code often and I am sure this will help anyone looking for a quick-fix solution to secure cookies.

The basic architecture is to create static methods to which you pass a cookie and get a encrypted version in return. It also conveniently retrieves the Algorithm to use as well as the key to encrypt/decrypt from the web.config file and can be adapted to retrieve/generate the key in other ways.

Step 1: Start off with our class.

using System.Security.Cryptography; //and other...

public class Security
{
//If you dont want ur methods to be static then use this and instantiate an object before use
//byte[] Key;
//string AlgorithmName;

public Security()
{
//If you dont want ur methods to be static then use this
//char[] chars = { ',' };
//string[] splits = ConfigurationManager.AppSettings["CookieSecurityKey"].Split(chars);
//AlgorithmName = splits[0];
//Key = new byte[Int32.Parse(splits[1])];// = KEY_64;
//for (int i = 2; i < Key.Length + 2; i++)
// Key[i - 2] = byte.Parse(splits[i].Trim());
}
...

You can store the key/algoritm name in the web.config like this:








Step 2: Create the basic methods that encode/decode a piece of string

public static string Encode(string value, Byte[] key, string AlgorithmName)
{
// Convert string data to byte array
byte[] ClearData = System.Text.Encoding.UTF8.GetBytes(value);

// Now create the algorithm from the provided name
SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create(AlgorithmName);
Algorithm.Key = key; //you can apply your own key mechs here
MemoryStream Target = new MemoryStream();

// Generate a random initialization vector (IV), helps to prevent brute-force
Algorithm.GenerateIV();
Target.Write(Algorithm.IV, 0, Algorithm.IV.Length);

// Encrypt information
CryptoStream cs = new CryptoStream(Target, Algorithm.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(ClearData, 0, ClearData.Length);
cs.FlushFinalBlock();

// Convert the encrypted stream back to string
return Convert.ToBase64String(Target.GetBuffer(), 0, (int)Target.Length);
}

public static string Decode(string value, Byte[] key, string AlgorithmName)
{
// Convert string data to byte array
byte[] ClearData = Convert.FromBase64String(value);

// Create the algorithm
SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create(AlgorithmName);
Algorithm.Key = key;
MemoryStream Target = new MemoryStream();

// Read IV and initialize the algorithm with it
int ReadPos = 0;
byte[] IV = new byte[Algorithm.IV.Length];
Array.Copy(ClearData, IV, IV.Length);
Algorithm.IV = IV;
ReadPos += Algorithm.IV.Length;

// Decrypt information
CryptoStream cs = new CryptoStream(Target, Algorithm.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(ClearData, ReadPos, ClearData.Length - ReadPos);
cs.FlushFinalBlock();

// Get the bytes from the memory stream and convert them to text
return System.Text.Encoding.UTF8.GetString(Target.ToArray());
}
Note: there methods are static so that you can use them directly from code without the additional line to create an object.

Step 3: Create the methods that encode/decode the cookie

public static HttpCookie EncodeCookie(HttpCookie cookie)
{
if (cookie == null) return null;

//get key and algorithm from web.config/appsettings
//Comment this section if you do now what this method to be static
char[] chars = { ',' };
string[] splits = ConfigurationManager.AppSettings["CookieEncodingKey"].Split(chars);
string AlgorithmName = splits[0];
byte[] Key = new byte[Int32.Parse(splits[1])];// = KEY_64;
for (int i = 2; i < Key.Length + 2; i++)
Key[i - 2] = byte.Parse(splits[i].Trim());

HttpCookie eCookie = new HttpCookie(cookie.Name);

for (int i = 0; i < cookie.Values.Count; i++)
{
string value = HttpContext.Current.Server.UrlEncode(Encode(cookie.Values[i], Key, AlgorithmName));
string name = HttpContext.Current.Server.UrlEncode(Encode(cookie.Values.GetKey(i), Key, AlgorithmName));
eCookie.Values.Set(name, value);
}
return eCookie;
}

public static HttpCookie DecodeCookie(HttpCookie cookie)
{
if (cookie == null) return null;

//Comment this section if you do now what this method to be static
char[] chars = { ',' };
string[] splits = ConfigurationManager.AppSettings["CookieEncodingKey"].Split(chars);
string AlgorithmName = splits[0];
byte[] Key = new byte[Int32.Parse(splits[1])];// = KEY_64;
for (int i = 2; i < Key.Length + 2; i++)
Key[i - 2] = byte.Parse(splits[i].Trim());

HttpCookie dCookie = new HttpCookie(cookie.Name);

for (int i = 0; i < cookie.Values.Count; i++)
{
string value = Decode(HttpContext.Current.Server.UrlDecode(cookie.Values[i]), Key, AlgorithmName);
string name = Decode(HttpContext.Current.Server.UrlDecode(cookie.Values.GetKey(i)), Key, AlgorithmName);
dCookie.Values.Set(name, value);
}
return dCookie;
}

At this point you have the basis setup and you can use the class in your code.

Encoding Example:

HttpCookie cookie = new HttpCookie("MySecureCookie");
cookie["ID"] = "39369a0d-975e-4456-9ade-3f04639fd309"; //recommended: use some unique value to later check for fraudulent cookies while retrieving
cookie["Name"] = username;
cookie["Email"] = email;

cookie = Security.EncodeCookie(cookie); //encode
cookie.Expires = DateTime.Now.AddDays(90);
Response.Cookies.Add(cookie);
...

Decoding Example:

HttpCookie cookie = context.Request.Cookies["MySecureCookie"];
cookie = Security.DecodeCookie(cookie); //decode

if (cookie["ID"] == "39369a0d-975e-4456-9ade-3f04639fd309") cookieChecksOut = true;
//process cookie
...

This code allows using a single generic implementation to use a variety of algorithms based on their merits and properties. I hope this will help a lot of beginners.

Wednesday, March 05, 2008

Port Forwarding solution for Dataone's new Siemens SL2-141 ADSL router/modem

Well what can I say about the Indian Telephony services. They dont do much else then screw up and are always proud of it. This time they have got a nice wifi enabled ADSL router and f'ed up its html interface such that the user cannot set anything other then the very basic settings. I dug around the internet but couldnt find any solution for portforwarding in this perticular device using the standard html interface. But my rusted college time networking skills finally sparked up the manual config options. Here Goes...

Btw, there is no streight forward way to do it from the html interface that the router provides as the firmware has been modified by Dataone and all the advanced features are gone. The only method is to do it manually.


Requirements

1. Siemens SL2-141 router's username and passward.(Default Username - admin, Passward - admin)
2. Siemens SL2-141 router configured for always-on internet. (Otherwise u need to dial to connect and internet connection will be on only one PC at a time, but then u dont need to port forward at all.)
3. A terminal utility like HyperTerminal at Start&gt;All Programs&gt;Accesseries&gt;Communication.
4. Static IP address and the port configured in your torrent client. (See utorrent wiki, Azureus wiki)
5. Obvious stuff - Dataone A/c, ISP login details, Windows/linux terminal utility, Assuming router at 192.168.1.1.


Method

1. Open HyperTerminal
2. Configure ur Location/area code if asked.
3. Enter some name at the 'New Connection' message box. Hit Ok.
4. In the 'Connect to' message box select 'Tcp/Ip(winsock)' under 'Connect Using' menu.
5. Enter 192.168.1.1 in 'Host Address'. Hit Ok.
6. Now u r in the terminal and it will ask for login/passward. type and press enter one by one.
7. Main menu: Type 6 and press Enter.
8. NAT menu: Type 1 and press Enter.
9. Virtual server menu: Type 1 and press Enter.
10.Service name - type anything like utorrent or text. Press Enter.
11.Protocol - Type 0. Press Enter.
12. External start port - Type the port of ur torrent client and Press Enter.
13. External end port - Type the port of ur torrent client and Press Enter.
14. Internal start port - Type the port of ur torrent client and Press Enter.
15. Internal end port - Type the port of ur torrent client and Press Enter.
16. Internal server IP address - Type the (static) IP of pc running ur torrent client and Press Enter.
17. See confirmation. Check using some web based port checking webpage or ur torrent client.
18. Exit the terminal. Done.


Misc

1. Port forwarding basics and method for other then dataone coustomers at portforward.com
2. utorrent's Port forwarding test at http://www.utorrent.com/testport.php?port=&lt;enter port here&gt;. ^
3. Dataone website. (Has Speed test, Webmail, Usage portal, Mail Client config steps etc)
4. Siemens SL2-141 Quick start guide(Pdf 1.31Mb, Illustrated), Manual(Pdf 5.44mb) and Datasheet.
5. Sample network configuration illustration.
6. Reset you modem from the HTML interface in case u mess up.

Now thank me for all the hardwark. :)

Sunday, February 10, 2008

Yahoo REJECTS Microsoft's $44.6 Billion takeover Offer (Part of World domination)!

I feel a bit disturbed about microsoft's 'world domination' plans. It is a scary glimpse of the future. If M$ keeps taking of the internet in such a fashion then it wont be long before groups like Anonymous, who are currently in the process of surgical strikes on the Chruch of scientology, declare similar wars on companies like microsoft. I personally would like to see Yahoo join hands with Google.

Anyways, have a look at this news item about yahoo's rejection and this Youtube video(s) about 'the message' of war from Anonymous which has already crossed 2 million views at the time of writing this blog entry.

You might also be wondering why i have written the word microsoft with a lower cap character. I intend this as my own little private display of resistance and ask anyone who is serious about the future of our race to fallow suite. [Looks for a sniper laser pointer ]

Powered by ScribeFire.