What I'm trying to accomplish is essentially creating a replacement for the Cookie object/methods in my MVC application that uses the same interface with a few additional methods.

The methods I want to add are custom methods to create encrypted cookies. These methods basically just encrypt the data being set in the cookie before setting it. A reverse method would decrypt the data after reading the cookie.

The reason I want to replace the built in the Cookie object is so that I can re-engineer the way the default methods behave to allow automatic encryption/decryption.

有帮助吗?

解决方案

While the HttpCookie class is sealed and cannot be inherited you can make your life easier by making an encrypted cookie class with an operator overload for ease of use.

public class EncryptedCookie
{
    public string Name { get; set; }

    public string Value { get; set; }

    private byte[] encryptionKey;

    private byte[] hmacKey;

    public EncryptedCookie()
    {
        // setup keys
        encryptionKey = Convert.FromBase64String(ConfigurationManager.AppSettings["encryption-key"]);
        this.hmacKey = Convert.FromBase64String(ConfigurationManager.AppSettings["hmac-key"]);
    }

    public static explicit operator HttpCookie(EncryptedCookie cookie)
    {
        if (string.IsNullOrEmpty(cookie.Name))
        {
            throw new ArgumentException("Encrypted cookie must have a name");
        }

        if (string.IsNullOrEmpty(cookie.Value))
        {
            throw new ArgumentException("Encrypted cookie must have a value");
        }

        return new HttpCookie(cookie.Name, cookie.Encrypt());
    }

    public static explicit operator EncryptedCookie(HttpCookie cookie)
    {
        if (cookie == null)
        {
            return null;
        }

        var result = new EncryptedCookie { Name = cookie.Name };
        result.Decrypt(cookie.Value);
        return result;
    }

    private string Encrypt()
    {
        var encryptor = new Encryptor<AesEngine, Sha256Digest>(Encoding.UTF8, this.encryptionKey, this.hmacKey);
        return encryptor.Encrypt(this.Value);
    }

    private void Decrypt(string cookieValue)
    {
        var encryptor = new Encryptor<AesEngine, Sha256Digest>(Encoding.UTF8, this.encryptionKey, this.hmacKey);
        string plainText = encryptor.Decrypt(cookieValue);
        if (string.IsNullOrEmpty(plainText))
        {
            throw new ArgumentException();
        }

        this.Value = plainText;
    }
}

To use this class you'll need my encryptor class as well as bouncycastle. This class performs an encryption of whatever value you input and a decryption when set from an http cookie that's already in the response. One thing that's nice with this is it will automatically generate an IV for you as well as an HMAC to verify there was no tampering with the cookie values. You will need Two separate keys, one for the HMAC and one for encryption. Generate these wisely as they are the most important part of the crypto system.

You can find the encryptor class under Encrypt and decrypt a string or you can override with whatever you want to use if there's something your company specifically uses.

Finally to use simply create an encrypted cookie and add it to the response:

EncryptedCookie cookie = new EncryptedCookie { Name = "MyCookie", Value = "Hide this!" };
Response.Cookies.Add((HttpCookie)cookie);

When you want to decrypt it simply cast the cookie back to an encrypted cookie:

var cookie = (EncryptedCookie)Request.Cookies["MyCookie"];
Response.Write(cookie.Value);

其他提示

I don't believe there is a way. Both the HttpRequest/HttpResponse objects which expose the Cookie instance are sealed, as it the HttpCookie class itself.

You might be able to work around by reimplementing the Request/Response using the HttpResponseWrapper/HttpRequestWrapper base classes, but it seems like a lot of work.

Good luck!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top