1 using System;
2 using System.Collections;
3 using System.Collections.Specialized;
4 using System.Text;
5 using System.Security.Cryptography;
6 using System.IO;
7
8 namespace Flanders.Library.WebControls.Resources
9 {
10 public sealed class SecureParams
11 {
12 const string c_EncryptionKey = "Your24Characterstring!!!";
13 ///
14 /// Encrypts the text using RijndaelManaged 256-bits encryption. Using the default key
15 ///
16 /// The text to encrypt.
17 /// A base64 encoded string that represents the encrypted data
18 public static string EncryptText(string strTxt)
19 {
20 return Encrypt(strTxt, c_EncryptionKey);
21 }
22
23 ///
24 /// Decrypts the text that was encrypted using the encrypt method of this class.
25 ///
26 /// The base64 encrypted string.
27 /// A decrypted string
28 public static string DecryptText(string strTxt)
29 {
30 return Decrypt(strTxt, c_EncryptionKey);
31 }
32
33 ///
34 /// Encrypts the text using RijndaelManaged 256-bits encryption. Using the provided encryption key
35 ///
36 /// The text to encrypt.
37 /// The encryption key (24 characters).
38 /// A base64 encoded string that represents the encrypted data
39 public static string Encrypt(string strTxt, string encryptKey)
40 {
41 byte[] byKey = { };
42 byte[] IV ={ 55, 103, 246, 79, 36, 99, 167, 3, 42, 5, 62, 83, 184, 7, 209, 13, 145, 23, 200, 58, 173, 10, 121, 222, 88, 09, 45, 67, 94, 12, 34, 5 };
43 try
44 {
45 byKey = Encoding.UTF8.GetBytes(encryptKey);
46 RijndaelManaged rm = new RijndaelManaged();
47 rm.BlockSize = 256;
48 rm.IV = IV;
49 rm.KeySize = 256;
50 rm.Key = new SHA256Managed().ComputeHash(byKey);
51 byte[] inputByteArray = Encoding.UTF8.GetBytes(strTxt);
52 MemoryStream ms = new MemoryStream();
53 CryptoStream cs = new CryptoStream(ms, rm.CreateEncryptor(), CryptoStreamMode.Write);
54 cs.Write(inputByteArray, 0, inputByteArray.Length);
55 cs.FlushFinalBlock();
56 return Convert.ToBase64String(ms.ToArray());
57 }
58 catch (Exception ex)
59 {
60 return ex.Message;
61 }
62 }
63
64 ///
65 /// Decrypts the text using RijndaelManaged 256-bits encryption. Using the provided encryption key
66 ///
67 /// The base64 encrypted string.
68 /// The encryption key (24 characters).
69 /// A decrypted string
70 public static string Decrypt(string strTxt, string decryptKey)
71 {
72 byte[] byKey = { };
73 byte[] IV ={ 55, 103, 246, 79, 36, 99, 167, 3, 42, 5, 62, 83, 184, 7, 209, 13, 145, 23, 200, 58, 173, 10, 121, 222, 88, 09, 45, 67, 94, 12, 34, 5 };
74 try
75 {
76 byKey = Encoding.UTF8.GetBytes(decryptKey);
77 RijndaelManaged rm = new RijndaelManaged();
78 rm.BlockSize = 256;
79 rm.IV = IV;
80 rm.KeySize = 256;
81 rm.Key = new SHA256Managed().ComputeHash(byKey);
82 byte[] inputByteArray = Convert.FromBase64String(strTxt);
83 MemoryStream ms = new MemoryStream();
84 CryptoStream cs = new CryptoStream(ms, rm.CreateDecryptor(), CryptoStreamMode.Write);
85 cs.Write(inputByteArray, 0, inputByteArray.Length);
86 cs.FlushFinalBlock();
87 System.Text.Encoding encoding = System.Text.Encoding.UTF8;
88 return encoding.GetString(ms.ToArray());
89 }
90 catch (Exception ex)
91 {
92 return ex.Message;
93 }
94 }
95
96 ///
97 /// Creates the params. This method should be used when you need to pass variables ie. from a page to a handler. It stores the encryption in
98 /// in the session state. This is the most secure option provided but can only be used with sessionstate for now.
99 ///
100 /// The key.
101 /// The param.
102 ///
103 /// This will store the encrypted value of the querystring in a session object (it expires and dissapears together with the session).
104 /// the sesionkey value should be passed (optionally as an encoded query string) as the querystring to the new page/handler.
105 ///
106 public static void CreateParams(string sessionkey, string param)
107 {
108 System.Web.HttpContext _context = System.Web.HttpContext.Current;
109 _context.Session[sessionkey] = EncryptText(param);
110 }
111
112 ///
113 /// Gets the params. This method should be used to get the params as a hashtable form the encrypted querystring
114 ///
115 /// The param.
116 /// A hashtable that contains the encrypted values from the querystring created with CreateParams
117 public static Hashtable GetParams(string sessionkey)
118 {
119 System.Web.HttpContext _context = System.Web.HttpContext.Current;
120 string var = DecryptText(_context.Session[sessionkey].ToString());
121 Hashtable ht = new Hashtable();
122 string[] vars = var.Split(Convert.ToChar("&"));
123 foreach (string s in vars)
124 {
125 ht.Add(s.Split(Convert.ToChar("="))[0], s.Split(Convert.ToChar("="))[1]);
126 }
127 return ht;
128 }
129
130 ///
131 /// Gets the params. This method should be used to get the params as a hashtable form the encrypted querystring
132 ///
133 /// The encrypted query string.
134 ///
135 /// A NameValueCollection that contains the decrypted values from the querystring
136 ///
137 public static NameValueCollection GetQueryKeys(string encryptedQueryString)
138 {
139 System.Web.HttpContext _context = System.Web.HttpContext.Current;
140 string var = DecodeQs(encryptedQueryString);
141 NameValueCollection ht = new NameValueCollection();
142 string[] vars = var.Split(Convert.ToChar("&"));
143 foreach (string s in vars)
144 {
145 ht[s.Split(Convert.ToChar("="))[0]] = s.Split(Convert.ToChar("="))[1];
146 }
147 return ht;
148 }
149
150 ///
151 /// Gets the params. This method should be used to get the params as a hashtable form the encrypted querystring
152 ///
153 /// The encrypted query string.
154 /// The encryption key.
155 ///
156 /// A NameValueCollection that contains the decrypted values from the querystring
157 ///
158 public static NameValueCollection GetQueryKeys(string encryptedQueryString, string encryptionKey)
159 {
160 System.Web.HttpContext _context = System.Web.HttpContext.Current;
161 string var = DecodeQs(encryptedQueryString,encryptionKey);
162 NameValueCollection ht = new NameValueCollection();
163 string[] vars = var.Split(Convert.ToChar("&"));
164 foreach (string s in vars)
165 {
166 ht[s.Split(Convert.ToChar("="))[0]] = s.Split(Convert.ToChar("="))[1];
167 }
168 return ht;
169 }
170
171 ///
172 /// Encodes the querystring using a default key and the expiration timestamp is set to 90 years.
173 ///
174 /// The query string.
175 ///
176 public static string EncodeQs(string qs)
177 {
178 return EncodeQs(qs, c_EncryptionKey);
179 }
180
181 ///
182 /// Encodes the querystring using a specified key and the expiration timestamp is set to 90 years.
183 ///
184 /// The query string.
185 /// The encryption key.
186 ///
187 public static string EncodeQs(string qs, string key)
188 {
189 return EncodeQs(qs, key, DateTime.Now.AddYears(90));
190 }
191
192 ///
193 /// Encodes the querystring using a specified key and the expiration timestamp is set to 90 years.
194 ///
195 /// The query string.
196 /// The encryption key.
197 ///
198 public static string EncodeQs(string qs, DateTime expiration)
199 {
200 return EncodeQs(qs, c_EncryptionKey, DateTime.Now.AddYears(90));
201 }
202
203 ///
204 /// Encodes the querystring using the specified key and the specified expiration date.
205 ///
206 /// The querystring.
207 /// The encryptionkey.
208 /// The expiration.
209 ///
210 public static string EncodeQs(string qs, string key, DateTime expiration)
211 {
212 System.Web.HttpContext _context = System.Web.HttpContext.Current;
213 string encrypted = EncryptText(qs + "," + expiration.ToString());
214 string query = encrypted + HashQuery(encrypted, key);
215 return query;
216 }
217 ///
218 /// Decodes the qs.
219 ///
220 /// The qs.
221 ///
222 public static string DecodeQs(string qs)
223 {
224 return DecodeQs(qs, c_EncryptionKey);
225 }
226
227 ///
228 /// Decodes the qs.
229 ///
230 /// The query string.
231 /// The encryption key (24 characters).
232 ///
233 public static string DecodeQs(string qs,string key)
234 {
235 qs = qs.Replace(" ", "+") ; //something doesn't handle spaces very well, so we replace them with a + sign
236 string encrypted = qs.Split(Convert.ToChar("-"))[0];
237 string hashVal = qs.Split(Convert.ToChar("-"))[1];
238 if (ValidateHash(hashVal,encrypted, key ))
239 {
240 string Qs = DecryptText(encrypted);
241 string[] vars = Qs.Split(Convert.ToChar(","));
242 string var = vars[0];
243 string date = vars[1];
244 DateTime tocheck = Convert.ToDateTime(date);
245 if (DateTime.Now > tocheck)
246 throw new QueryStringExpiredException("Url expired... "+ date + " " +DateTime.Now.ToString());
247 return var;
248 }
249 else
250 throw new QueryStringInvalidHashException("Url has been messed with...");
251 }
252
253 private static string HashQuery(string value, string key)
254 {
255 System.Security.Cryptography.MACTripleDES mac3des = new System.Security.Cryptography.MACTripleDES();
256 System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
257 mac3des.Key = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
258 return Convert.ToChar("-") + Convert.ToBase64String(mac3des.ComputeHash(Encoding.UTF8.GetBytes(value)));
259 }
260
261 private static bool ValidateHash(string value,string data, string key)
262 {
263 String calcHash = "";
264 String storedHash = "";
265 MACTripleDES mac3des = new MACTripleDES();
266 MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
267 mac3des.Key = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key));
268 try
269 {
270 storedHash = Encoding.UTF8.GetString(System.Convert.FromBase64String(value));
271 calcHash = Encoding.UTF8.GetString(mac3des.ComputeHash(Encoding.UTF8.GetBytes(data)));
272 if (storedHash != calcHash)
273 {
274 return false;
275 }
276 }
277 catch
278 {
279 throw new QueryStringInvalidHashException("Invalid comparison hash for query string.");
280 }
281 return true;
282 }
283 }
284
285 public class QueryStringExpiredException : Exception
286 {
287 public QueryStringExpiredException() : base() { }
288 public QueryStringExpiredException(string message) : base(message) { }
289 public QueryStringExpiredException(string message, Exception ex):base(message,ex){}
290 }
291
292 public class QueryStringInvalidHashException : Exception
293 {
294 public QueryStringInvalidHashException() : base() { }
295 public QueryStringInvalidHashException(string message) : base(message) { }
296 public QueryStringInvalidHashException(string message, Exception ex) : base(message, ex) { }
297 }
298 }