|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionI really have some good laughs when I tamper with cookies on my machine and watch the results when it is submitted back to the site. On the other hand, I don’t want any one to do the same to the cookies that I make! Cookies, most of the times, shouldn’t be in plain text, at least, they should be tamper-proof! Revealing the content of your cookies might give curious and malicious people an idea about your application’s architecture, and that might help hacking it. ASP.NET encodes and hashes its authorization ticket, making it secure and tamper-proof. However, the methods used to secure authorization cookies are inaccessible from outside the .NET framework libraries, so you can’t protect your own cookie using these methods; you need to protect it yourself using your own encryption key, encoding and hashing algorithms. Of course, you shouldn’t save valuable information in your cookies, but if you have to, then this library is at your disposal. BackgroundBefore you start using this code, if you do not know what ASP.NET uses the To be able to access this internal class, I had to use reflection to be able to access the Eric Newton has a similar and good article on CP: Encrypting cookies to prevent tampering. However, that code is made for .NET 1.1 and it doesn't work with .NET 2.0 (but it does with some modifications); moreover, its resulting cipher text is in binary format versus being in encrypted format, and I don't know if this is a security risk. Also, I am accessing a higher level class There is also another available method for encoding cookies, by using the Obtaining Reference to the CookieProtectionHelper Class via ReflectionTo be able to access public static class CookieProtectionHelperWrapper {
private static MethodInfo _encode;
private static MethodInfo _decode;
static CookieProtectionHelperWrapper() {
// obtaining a reference to System.Web assembly
Assembly systemWeb = typeof(HttpContext).Assembly;
if (systemWeb == null) {
throw new InvalidOperationException(
"Unable to load System.Web.");
}
// obtaining a reference to the internal class CookieProtectionHelper
Type cookieProtectionHelper = systemWeb.GetType(
"System.Web.Security.CookieProtectionHelper");
if (cookieProtectionHelper == null) {
throw new InvalidOperationException(
"Unable to get the internal class CookieProtectionHelper.");
}
// obtaining references to the methods of CookieProtectionHelper class
_encode = cookieProtectionHelper.GetMethod(
"Encode", BindingFlags.NonPublic | BindingFlags.Static);
_decode = cookieProtectionHelper.GetMethod(
"Decode", BindingFlags.NonPublic | BindingFlags.Static);
if (_encode == null || _decode == null) {
throw new InvalidOperationException(
"Unable to get the methods to invoke.");
}
}
public static string Encode(CookieProtection cookieProtection,
byte[] buf, int count) {
return (string)_encode.Invoke(null,
new object[] { cookieProtection, buf, count });
}
public static byte[] Decode(CookieProtection cookieProtection,
string data) {
return (byte[])_decode.Invoke(null,
new object[] { cookieProtection, data });
}
}
MachineKeyCryptography: A Cryptography Class Based on MachineKey
public static string Encode(string text, CookieProtection cookieProtection) {
if (string.IsNullOrEmpty(text) || cookieProtection == CookieProtection.None) {
return text;
}
byte[] buf = Encoding.UTF8.GetBytes(text);
return CookieProtectionHelperWrapper.Encode(cookieProtection, buf, buf.Length);
}
public static string Decode(string text, CookieProtection cookieProtection) {
if (string.IsNullOrEmpty(text)) {
return text;
}
byte[] buf;
try {
buf = CookieProtectionHelperWrapper.Decode(cookieProtection, text);
}
catch(Exception ex) {
throw new InvalidCypherTextException(
"Unable to decode the text", ex.InnerException);
}
if (buf == null || buf.Length == 0) {
throw new InvalidCypherTextException(
"Unable to decode the text");
}
return Encoding.UTF8.GetString(buf, 0, buf.Length);
}
HttpSecureCookie ClassThis static class will handle the service of securing the content of a cookie. Also, it provides a service to clone a cookie. This class uses public static class HttpSecureCookie {
public static HttpCookie Encode(HttpCookie cookie) {
return Encode(cookie, CookieProtection.All);
}
public static HttpCookie Encode(HttpCookie cookie,
CookieProtection cookieProtection) {
HttpCookie encodedCookie = CloneCookie(cookie);
encodedCookie.Value =
MachineKeyCryptography.Encode(cookie.Value, cookieProtection);
return encodedCookie;
}
public static HttpCookie Decode(HttpCookie cookie) {
return Decode(cookie, CookieProtection.All);
}
public static HttpCookie Decode(HttpCookie cookie,
CookieProtection cookieProtection) {
HttpCookie decodedCookie = CloneCookie(cookie);
decodedCookie.Value =
MachineKeyCryptography.Decode(cookie.Value, cookieProtection);
return decodedCookie;
}
public static HttpCookie CloneCookie(HttpCookie cookie) {
HttpCookie clonedCookie = new HttpCookie(cookie.Name, cookie.Value);
clonedCookie.Domain = cookie.Domain;
clonedCookie.Expires = cookie.Expires;
clonedCookie.HttpOnly = cookie.HttpOnly;
clonedCookie.Path = cookie.Path;
clonedCookie.Secure = cookie.Secure;
return clonedCookie;
}
}
Using the CodeUsing HttpCookie cookie = new HttpCookie("UserName", "Terminator");
cookie.Expires = DateTime.Now.AddDays(1);
HttpCookie encodedCookie = HttpSecureCookie.Encode(cookie);
Response.Cookies.Add(encodedCookie);
To decode an encoded cookie: HttpCookie cookie = Request.Cookies["UserName"];
lblDisplayBefore.Text = cookie.Value;
HttpCookie decodedCookie = HttpSecureCookie.Decode(cookie);
To use LimitationsThis library uses reflection, so it might break with the next version of .NET. Also, it doesn't work with .NET 1.1. Reflection might have some performance implication; however, I used an assembly that is already loaded, "System.Web.dll", and I am only using reflection once across the life time of the application, to gain extra performance. ConclusionIf you don't want a sophisticated cookie encryption service, if you don't want to mind the encryption key, and if you don't want to create your own encryption algorithm, then this library is for you! Comments and suggestions are welcome. Please vote if you like this article (or if you didn't). History
|
||||||||||||||||||||||