25

I would like to encrypt cookies in ASP.NET.

I have followed the method in this article, but it has the drawback that is uses reflection on an internal method. This has caused it to be flagged in a code review -- it is not future-proof as the internal implementation may change.

Is there a method with identical functionality which doesn't require using encryption on internal methods?

I am using .NET Framework 3.5 SP1 (Assume I cannot change framework versions)

frankadelic
  • 20,543
  • 37
  • 111
  • 164

2 Answers2

38

You don't need to roll your own any more.

.Net 4.5 has MachineKey.Protect() and MachineKey.Unprotect().

System.Web.Security.MachineKey

.Net 4.0 has MachineKey.Encode() and MachineKey.Decode(). You should just set the MachineKeyProtection to 'All'. These are now obsolete though and you should use the newer ones if you have 4.5.

Note if you try and use these in something like a console app instead of ASP.Net it seems to generate a new key with every app restart. I only checked it quickly but in ILSpy it looks like it generates its own defaults if the appropriate app.setting are missing.

I haven't been able to find a non-ASP.Net equivalent.

mattmanser
  • 5,719
  • 3
  • 38
  • 50
  • 2
    how it can be used in farms? where we have multiple servers behind a load-balancer – Mahmoud Samy Feb 03 '14 at 11:25
  • 11
    I assume they'd have to share the same machine key, which you can set in web.config rather than use the default one. See http://stackoverflow.com/questions/3855666/adding-machinekey-to-web-config-on-web-farm-sites and http://msdn.microsoft.com/en-us/library/ff649308.aspx#paght000007_webfarmdeploymentconsiderations – mattmanser Feb 04 '14 at 12:00
21

Why not just use the encryption found in System.Security.Cryptography to encrypt and decrypt the cookie name and value when it's sensitive? You can write some utility functions to manage it pretty easily. Example utility functions:

private static void SetEncryptedCookie(string name, string value)
{
    var encryptName = SomeEncryptionMethod(name);
    Response.Cookies[encryptName].Value = SomeEncryptionMethod(value);
    //set other cookie properties here, expiry &c.
    //Response.Cookies[encryptName].Expires = ...
}

private static string GetEncryptedCookie(string name)
{
    //you'll want some checks/exception handling around this
    return SomeDecryptionMethod(
               Response.Cookies[SomeDecryptionMethod(name)].Value);
}
jball
  • 24,791
  • 9
  • 70
  • 92
  • The internal method I mentioned adds some randomness to the encryption so the encrypted text is different every time. The method you mentioned doesn't - I think. – frankadelic Dec 06 '10 at 00:12
  • @frankadelic - an encrpytion method that depends on appending random text to remain secure is, I think, inherently flawed. Any robust machine key or other private key based symmetric encryption should be sufficient. – jball Dec 06 '10 at 00:38
  • 3
    huh? Isn't it recommended practice to add random salt when encrypting data? – frankadelic Dec 06 '10 at 00:58
  • 4
    @frankadelic, salts are good for preventing brute force cracking of user supplied passwords via rainbow tables. Machine keys and other large generated private keys do not benefit from salting. – jball Dec 06 '10 at 01:28
  • See the wiki on crytographic salting http://en.wikipedia.org/wiki/Salt_(cryptography) for a more complete explanation. – jball Dec 06 '10 at 01:30
  • 1
    Encryption implementation is deceptively easy, I've ported google's [Keyczar to .net](http://jbtule.github.com/keyczar-dotnet/) the encapsulates much more, such as authenticated encryption and key rotation both are very important when encrypting cookies. – jbtule Jan 22 '13 at 14:04
  • 1
    Wow so much confusion between hashing and encrypting here. Salting is used in hashing to prevent rainbow tables. It *is* recommended in encryption that the first block (size of key) is also random, this is known as the Initialization Vector, this makes sure that the output of an encryption is never the same twice for the same data. In .NET most of the encryption methods have an IV property which is initialized as random, you will need to include this though in your output (it doesn't need to be kept secret) so that you can decrypt it. What does need to be kept secret is your keys – Sekhat May 21 '13 at 08:55
  • I'm sorry @Sekhat, I don't see the confusion? Is there something in what I posted about salting that's incorrect? – jball May 21 '13 at 16:34
  • Salts are used when cryptographically hashing something to make the hash somewhat different than it would be without it. Mostly so giant lists of hash values can't be used in finding a valid collision. When encrypting values, like the OP wants here, salting isn't used. The closest equivalent is Initialization Vectors, which should be random and different for each set of data being separately encrypted, it serves a similar purpose, to prevent attacks against block cyphers. Though the nature of the attack is somewhat different. – Sekhat May 23 '13 at 13:17
  • @Sekhat, So essentially what I said in my second comment with a side reference to IVs, or is my second comment mis-stating something? – jball May 23 '13 at 16:04
  • I can't even believe this question & answer has so many votes. You can encrypt the value of a cookie as much as you like. But you're still surely going to be able to circumvent the entire encryption by simply copying the cookie, or cookie hijacking. – dan richardson Dec 09 '13 at 10:35
  • @dan, it entirely depends on why the cookies are encrypted. If it is so the contents can't be understood on the client side, then this accomplishes that. – jball Dec 09 '13 at 20:45
  • Its been four years, but is this still applicable and a secure way to encrypt cookies? – Micro Sep 19 '14 at 15:10
  • @MicroR it depends on which cipher you use which you can research apart from this (e.g. [How secure is AES-256?](http://crypto.stackexchange.com/questions/2251/how-secure-is-aes-256)) but generally speaking, yeah, it's secure if the cipher used is secure and the keys are well protected. – jball Sep 19 '14 at 18:17
  • Thanks for this!! Few suggestions: The GetEncryptedCookie() should use Request cookies. Also, make sure that the encrypted name of the cookie does not contain an = sign in it. Browsers don't seem to like that. Also, in the same function, you should be encrypting the NAME. – Arthur Hylton Jun 08 '17 at 16:00