-
Notifications
You must be signed in to change notification settings - Fork 0
/
SecureCookie.cs
168 lines (138 loc) · 4.74 KB
/
SecureCookie.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections.Specialized;
using System.Text;
using System.Web.Security;
namespace Point4
{
public abstract class SecureCookie
{
public HttpCookie Cookie { get; protected set; }
public bool IsEncrypted { get; protected set; }
public string Name { get { return Cookie.Name; } set { Cookie.Name = value; } }
public string Path { get { return Cookie.Path; } set { Cookie.Path = value; } }
public bool Secure { get { return Cookie.Secure; } set { Cookie.Secure = value; } }
public bool HttpOnly { get { return Cookie.HttpOnly; } set { Cookie.HttpOnly = value; } }
public string Domain { get { return Cookie.Domain; } set { Cookie.Domain = value; } }
public DateTime Expires { get { return Cookie.Expires; } set { Cookie.Expires = value; } }
public string Value { get { return Cookie.Value; } }
public bool? HasKeys
{
get
{
return IsEncrypted ? new Nullable<bool> () : new Nullable<bool> (Cookie.HasKeys);
}
}
public NameValueCollection Values
{
get
{
return IsEncrypted ? new NameValueCollection () : Cookie.Values;
}
}
public override string ToString()
{
return IsEncrypted ? "Encrypted Cookie" : Cookie.ToString ();
}
public abstract EncryptedCookie Encrypt();
public abstract DecryptedCookie Decrypt();
public SecureCookie(HttpCookie cookie, bool isEncrypted = false)
{
this.Cookie = cookie;
this.IsEncrypted = isEncrypted;
}
public SecureCookie(string Name, string Value)
{
this.Cookie = new HttpCookie (Name, Value);
}
public SecureCookie(string Name, IDictionary<string, string> dictionary)
{
var cookie = new HttpCookie (Name);
foreach (var kv in dictionary)
cookie.Values.Add (kv.Key, kv.Value);
this.Cookie = cookie;
}
public static implicit operator SecureCookie(HttpCookie cookie)
{
return new EncryptedCookie (cookie);
}
}
public class EncryptedCookie : SecureCookie
{
public EncryptedCookie(HttpCookie cookie) : base(cookie)
{
cookie.Value = encrypt (cookie.Value);
this.IsEncrypted = true;
}
public EncryptedCookie(DecryptedCookie cookie) : this(cookie.Cookie)
{
}
private string encrypt(string message)
{
return MachineKey.Encode (Encoding.Unicode.GetBytes (message), MachineKeyProtection.Encryption);
}
public override EncryptedCookie Encrypt()
{
return this;
}
public override DecryptedCookie Decrypt()
{
return new DecryptedCookie (this);
}
}
public class DecryptedCookie : SecureCookie
{
public DecryptedCookie(EncryptedCookie cookie) : this(cookie.Cookie)
{
}
public DecryptedCookie(HttpCookie cookie) : base (cookie, true)
{
decrypt (cookie);
this.Cookie = cookie;
this.IsEncrypted = false;
}
public override EncryptedCookie Encrypt()
{
return new EncryptedCookie (this.Cookie);
}
public override DecryptedCookie Decrypt()
{
return this;
}
void decrypt(HttpCookie cookie)
{
try
{
var values = Encoding.Unicode.GetString (MachineKey.Decode (cookie.Value, MachineKeyProtection.Encryption)).Replace ("%3d", "=").Replace ("%26", ";").Split ('&');
if (values.Length > 0)
{
cookie.Values.Clear ();
if (values.All (x => x.Contains ("=") && !x.EndsWith ("=")))
{
foreach (var value in values)
{
var kv = value.Split ('=');
cookie.Values.Add (kv[0], kv[1]);
}
}
else
{
cookie.Value = values[0];
}
}
}
catch (HttpException ex)
{
if (ex.Message == "Unable to validate data.")
{
//assume cookie is not encrypted
}
else
throw;
}
IsEncrypted = false;
}
}
}