|
|
Comments and Discussions
|
|
 |

|
On 4.0 framework HttpSecureCookie was working fine, but I updated my app to 4.5 and I got:
System.ArgumentException: Object type 'System.Int32' cannot be converted to the type 'System.Web.Security.Cryptography.Purpose'. en System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) in System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) en System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) in System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in AdamTibi.Web.Security.CookieProtectionHelperWrapper.Encode(CookieProtection cookieProtection, Byte[] buf, Int32 count) en AdamTibi.Web.Security.MachineKeyCryptography.Encode(String text, CookieProtection cookieProtection) en AdamTibi.Web.Security.HttpSecureCookie.Encode(HttpCookie cookie, CookieProtection cookieProtection) in AdamTibi.Web.Security.HttpSecureCookie.Encode(HttpCookie cookie)
I hope you could test it. Thank you
|
|
|
|

|
Later versions of ASP.NET has added the functionality provided by this article, so, if you are on 4.5, you should be using methods from the framework.
Make it simple, as simple as possible, but not simpler.
|
|
|
|

|
For new implementations of this examples I suggest using System.Web.Security.MachineKey class instead of internal CookieProtectionHelper and reflection.
private static string Encode(string text)
{
if (string.IsNullOrEmpty(text))
return text;
byte[] buf = Encoding.UTF8.GetBytes(text);
return System.Web.Security.MachineKey.Encode(buf, MachineKeyProtection.All);
}
private static string Decode(string text)
{
if (string.IsNullOrEmpty(text))
return text;
byte[] buf = System.Web.Security.MachineKey.Decode(text, MachineKeyProtection.All);
return Encoding.UTF8.GetString(buf);
}
Works like a charm.
|
|
|
|

|
Hi Vasekz
In .NET 2.0 this API did not exist (this is when the article was written).
Make it simple, as simple as possible, but not simpler.
|
|
|
|

|
Oh, it's very safe and simple.
But this class is asp.net v.4.0, ys there any equivalence with 3.5?
|
|
|
|

|
Dear Sir,
I used your Dll file in my code but i m facing Problem.
like I have a page where i put 2 Buttons "Add", "Display".
if i call encode and decode both function on "Add" button then its showing last value.
but if i click one by one like firstly "Add" then "Display" then its showing Correct Result.
for Ex:=
****************************
string sShoppingCartCookieName = "ashutestcookie";
protected void Add_Click(object sender, EventArgs e)
{
AddToShoppingCart(1, 1, 1, "voucher");
HttpCookie oCookie = (HttpCookie)HttpContext.Current.Request.Cookies[sShoppingCartCookieName];
HttpCookie decodedCookie = HttpSecureCookie.Decode(oCookie);
string sProductID = decodedCookie.Values["quantity"].ToString();
Response.Write(sProductID);
}
**********************************
protected void Display_Click(object sender, EventArgs e)
{
HttpCookie oCookie = (HttpCookie)HttpContext.Current.Request.Cookies[sShoppingCartCookieName];
HttpCookie decodedCookie = HttpSecureCookie.Decode(oCookie);
string sProductID = decodedCookie.Values["quantity"].ToString();
Response.Write(sProductID);
}
**************************
public void AddToShoppingCart(int item_ID, int quantity, int cid, string vouchervalue)
{
if (HttpContext.Current.Request.Cookies[sShoppingCartCookieName] == null)
{
HttpCookie oCookie = new HttpCookie(sShoppingCartCookieName);
//Set Cookie to expire in 3 hours
oCookie.Expires = DateTime.Now.AddHours(1);
oCookie.Values["item_ID"] = item_ID.ToString();
oCookie.Values["quantity"] = quantity.ToString();
oCookie.Values["cid"] = cid.ToString();
oCookie.Values["vouchervalue"] = vouchervalue;//new added on 250510
// oCookie.Domain = sShoppingCartCookie_DomainName;
oCookie.HttpOnly = true;
HttpCookie encodedCookie = HttpSecureCookie.Encode(oCookie);
HttpContext.Current.Response.Cookies.Add(encodedCookie);
}
else
{
bool bExists = false;
char[] sep = { ',' };
HttpCookie decodedCookie = (HttpCookie)HttpContext.Current.Request.Cookies[sShoppingCartCookieName];
HttpCookie oCookie = HttpSecureCookie.Decode(decodedCookie);
oCookie.Expires = DateTime.Now.AddHours(1);
//Check if Cookie already contain same item
string sProdID = oCookie.Values["item_ID"].ToString();
string sQuantity = oCookie.Values["quantity"].ToString();
string scid = oCookie.Values["cid"].ToString();
string svouchervalue = oCookie.Values["vouchervalue"].ToString();//new added on 250510
string[] arrCookie = sProdID.Split(sep);
string[] arrQuantityCookie = sQuantity.Split(sep);
string[] arrCidCookie = scid.Split(sep);
string[] arrVouchervalueCookie = svouchervalue.Split(sep);//new added on 250510
for (int i = 0; i < arrCookie.Length; i++)
{
if (arrCookie[i].Trim() == item_ID.ToString().Trim() && arrCidCookie[i].Trim() == cid.ToString())
{
bExists = true;
if (arrVouchervalueCookie[i] != "P")// "P" denoted promotion)
{
//Update Quantity
this.UpdateShoppingCart(item_ID, quantity, cid);
}
}
}
if (!bExists)
{
if (oCookie.Values["item_ID"].Length == 0)
{
oCookie.Values["item_ID"] = item_ID.ToString();
oCookie.Values["quantity"] = quantity.ToString();
oCookie.Values["cid"] = cid.ToString();
oCookie.Values["vouchervalue"] = vouchervalue.ToString();//new added on 250510
}
else
{
oCookie.Values["item_ID"] = oCookie.Values["item_ID"] + "," + item_ID;
oCookie.Values["quantity"] = oCookie.Values["quantity"] + "," + quantity;
oCookie.Values["cid"] = oCookie.Values["cid"] + "," + cid;
oCookie.Values["vouchervalue"] = oCookie.Values["vouchervalue"] + "," + vouchervalue;//new added on 250510
}
// oCookie.Domain = sShoppingCartCookie_DomainName;
oCookie.HttpOnly = true;
oCookie.Secure = true;
HttpCookie encodedCookie = HttpSecureCookie.Encode(oCookie);
HttpContext.Current.Response.Cookies.Add(encodedCookie);
}
}
}
*******************************
public void UpdateShoppingCart(int item_ID, int quantity, int cid)
{
if (HttpContext.Current.Request.Cookies[sShoppingCartCookieName] == null)
{
//Do nothing
}
else
{
char[] sep = { ',' };
//HttpCookie oCookie = (HttpCookie)HttpContext.Current.Request.Cookies[sShoppingCartCookieName];
////Set Cookie to expire in 3 hours
//oCookie.Expires = DateTime.Now.AddHours(Global.dShoppingCartCookieExpires);
HttpCookie decodedCookie = (HttpCookie)HttpContext.Current.Request.Cookies[sShoppingCartCookieName];
//Set Cookie to expire in 3 hours
decodedCookie.Expires = DateTime.Now.AddHours(1);
HttpCookie oCookie = HttpSecureCookie.Decode(decodedCookie);
//Check if Cookie already contain same item
string sProdID = oCookie.Values["item_ID"].ToString();
string squantity = oCookie.Values["quantity"].ToString();
string scid = oCookie.Values["cid"].ToString();
string svouchervalue = oCookie.Values["vouchervalue"].ToString();//new added on 250510
string[] arrCookie = sProdID.Split(sep);
string[] arrCookie1 = squantity.Split(sep);
string[] arrCookie4 = scid.Split(sep);
string[] arrCookie6 = svouchervalue.Split(sep);//new added on 250510
string[] arrCookie2 = new string[arrCookie.Length];
string[] arrCookie3 = new string[arrCookie1.Length];
string[] arrCookie5 = new string[arrCookie4.Length];
string[] arrCookie7 = new string[arrCookie6.Length];//new added on 250510
int j = 0;
for (int i = 0; i < arrCookie.Length; i++)
{
if (arrCookie[i].Trim() == item_ID.ToString() && arrCookie4[i].Trim() == cid.ToString())
{
arrCookie2[j] = arrCookie[i];
arrCookie5[j] = arrCookie4[i];
arrCookie7[j] = arrCookie6[i];//new added on 250510
int quan = Convert.ToInt32(arrCookie1[i].ToString());
quan = quan + quantity;
arrCookie3[j] = quan.ToString();
j++;
}
else
{
arrCookie2[j] = arrCookie[i];
arrCookie3[j] = arrCookie1[i];
arrCookie5[j] = arrCookie4[i];
arrCookie7[j] = arrCookie6[i];//new added on 250510
j++;
}
}
string sCookieID = "";
string sCookieID2 = "";
string sCookieID3 = "";
string sCookieID4 = "";//new added on 250510
for (int i = 0; i < arrCookie2.Length; i++)
{
sCookieID = sCookieID + arrCookie2[i] + ",";
sCookieID2 = sCookieID2 + arrCookie3[i] + ",";
sCookieID3 = sCookieID3 + arrCookie5[i] + ",";
sCookieID4 = sCookieID4 + arrCookie7[i] + ",";//new added on 250510
}
if (sCookieID.Length > 0)
{
oCookie.Values["item_ID"] = sCookieID.Substring(0, sCookieID.Length - 1);
oCookie.Values["quantity"] = sCookieID2.Substring(0, sCookieID2.Length - 1);
oCookie.Values["cid"] = sCookieID3.Substring(0, sCookieID3.Length - 1);
oCookie.Values["vouchervalue"] = sCookieID4.Substring(0, sCookieID4.Length - 1);//new added on 250510
}
else
{
oCookie.Values["item_ID"] = "";
oCookie.Values["quantity"] = "";
oCookie.Values["cid"] = "";
oCookie.Values["vouchervalue"] = "";
}
// oCookie.Domain = Global.sShoppingCartCookie_DomainName;
oCookie.HttpOnly = true;
// HttpContext.Current.Response.Cookies.Add(oCookie);
//HttpCookie encodedCookie = HttpSecureCookie.Encode(oCookie);
//HttpContext.Current.Response.Cookies.Add(encodedCookie);
HttpCookie encodedCookie = new HttpCookie(sShoppingCartCookieName);
encodedCookie = HttpSecureCookie.Encode(oCookie);
if (Request.Cookies[sShoppingCartCookieName] != null)
{
HttpContext.Current.Response.Cookies.Add(encodedCookie);
}
}
}
***********************
ashutosh kumar jha
|
|
|
|

|
I am using this to encrypt and decrypt cookies in my website.
I have found that certain web servers in the farm cannot decrypt cookies created by others.
However, I took special care to sync up the values of machineKey validationKey and machineKey decryptionKey across all nodes in the web farm.
What is the problem? Is there some other config value that needs to be synced across the servers?
I am running IIS7 and .NET 3.5 SP1.
|
|
|
|

|
Found the issue. The security patches were out of sync on the servers.
The following patch appears to affect the way this algorithm works:
http://www.microsoft.com/technet/security/bulletin/ms10-070.mspx
|
|
|
|

|
I've used this for a couple of years on my web apps; it's been working great. Suddenly, a month or so ago, it started occasionally throwing errors. This only happens 5 to 15 times a day, on a site with thousands of hits per day.
Before anyone asks, yes, the web site is on a server farm and I do specify the machine key in the web config file. I haven't made any changes that could account for this.
Here are a couple of the errors from our error notification emails, which unwind the inner exceptions:
Error Ticket is: VSIIS1_11-04-2010___3
Message(0): /Login.aspx, IP: 209.99.19.8, Raw User Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Stack Trace(0):
Source(0): Error.aspx
Message(1): Exception of type 'System.Web.HttpUnhandledException' was thrown.
Stack Trace(1): at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.login_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Source(1): System.Web
Message(2): Unable to decode the text
Stack Trace(2): at AdamTibi.Web.Security.MachineKeyCryptography.Decode(String text, CookieProtection cookieProtection)
at AdamTibi.Web.Security.HttpSecureCookie.Decode(HttpCookie cookie, CookieProtection cookieProtection)
at AdamTibi.Web.Security.HttpSecureCookie.Decode(HttpCookie cookie)
at Global.get_AccessAccountID()
at Global.SetPreferenceCookies()
at _Default.Authenticate(String cUser, String cPass, String& cFailureText)
at _Default.Login1_Authenticate(Object sender, AuthenticateEventArgs e)
at System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
at System.Web.UI.WebControls.Login.AttemptLogin()
at System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Source(2): AdamTibi.Web.Security
Message(3): Unable to validate data.
Stack Trace(3): at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo, Boolean signData)
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo)
at System.Web.Security.CookieProtectionHelper.Decode(CookieProtection cookieProtection, String data)
Source(3): System.Web
Error Ticket is: VSIIS2_11-04-2010___2
Message(0): /Login.aspx, IP: 206.216.34.171, Raw User Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648)
Stack Trace(0):
Source(0): Error.aspx
Message(1): Exception of type 'System.Web.HttpUnhandledException' was thrown.
Stack Trace(1): at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.login_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Source(1): System.Web
Message(2): Unable to decode the text
Stack Trace(2): at AdamTibi.Web.Security.MachineKeyCryptography.Decode(String text, CookieProtection cookieProtection)
at AdamTibi.Web.Security.HttpSecureCookie.Decode(HttpCookie cookie, CookieProtection cookieProtection)
at AdamTibi.Web.Security.HttpSecureCookie.Decode(HttpCookie cookie)
at Global.get_AccessAccountID()
at Global.SetPreferenceCookies()
at _Default.Authenticate(String cUser, String cPass, String& cFailureText)
at _Default.Login1_Authenticate(Object sender, AuthenticateEventArgs e)
at System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e)
at System.Web.UI.WebControls.Login.AttemptLogin()
at System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e)
at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args)
at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e)
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Source(2): AdamTibi.Web.Security
Message(3): Length of the data to decrypt is invalid.
Stack Trace(3): at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo)
at System.Web.Security.CookieProtectionHelper.Decode(CookieProtection cookieProtection, String data)
Source(3): mscorlib
I thought at first that we were starting to get hits from mobile devices that were causing the problem; adding the raw user agent to the error notification proved that that is not the case.
My best guess is that some Microsoft patch may have caused the problem.
It's running on IIS6 on Windows Server 2003 (virtual machines) and ASP.Net 2.0.
If anyone has any ideas, I'd really appreciate it. Remember, the problem only occurs a few times each day - usually it works fine.
Anyway, thanks for the library - it's worked great up to now.
|
|
|
|

|
Hi Chuck we are also getting the same problem and we guess its a Microsoft patch. Better still how did you solve this problem? Its still a good library.
|
|
|
|

|
I actually didn't solve the problem. The place where I was using encryption wasn't really critical, so I just whipped up a custom class to substitute for this one using a simple substitution cipher that I could get in place quickly. Later if I need to I might go back and rewrite the custom class to replace the simple cipher with something using the .Net encryption classes.
|
|
|
|
|

|
What's the difference between using this and using System.Web.Security.MachineKey.Encrypt() ?
|
|
|
|

|
It seems that class is only available in .NET Framework version 4. This article was targeting .NET Framework 2.0.
|
|
|
|

|
Ah right... stupid me x_x
|
|
|
|

|
Thanks for the props in your article.
|
|
|
|

|
Since this uses Reflection, I gather that this will not run in a default Medium Trust environment at a hosting provider. Any idea how to do this so it will work?
Perhaps you could implement one of the Crypto providers in the System.Security.Cryptography namespace?
|
|
|
|

|
Hi
I never tried this in a medium trus enviroment.
You could always refer to your own encryption strategyMake it simple, as simple as possible, but not simpler.
|
|
|
|
|

|
Thank you Ziad
Make it simple, as simple as possible, but not simpler.
|
|
|
|

|
hi adam, i've a login page with a checkbox if i want to remember password. If this checkbox is checked, i encode the password in the cookies . I've a problem when i compile in debug with visual it's OK but if i launch direct my site (http://localhost/mysite) i've the following error message:Padding is invalid and cannot be removed if i delete my cookies and i try again it's ok but if i launch again with visual (without delete the cookies) in debug i've the same error source:mscorlib Line 58: catch(Exception ex) { Line 59: throw new InvalidCypherTextException("Unable to decode the text", ex.InnerException); Line 60: } Line 61: if (buf == null || buf.Length == 0) { Source File: C:\MJL\MySite\Sources\MySite_ClassLibrary\Security\MachineKeyCryptography.cs Line: 59 Stack trace [CryptographicException: Padding is invalid and cannot be removed.] System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast) +1490188 System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) +306 System.Security.Cryptography.CryptoStream.FlushFinalBlock() +30 System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, Boolean useValidationSymAlgo) +154 System.Web.Security.CookieProtectionHelper.Decode(CookieProtection cookieProtection, String data) +79 [InvalidCypherTextException: Unable to decode the text] have you an idea? thanks
|
|
|
|

|
Hi,
Recheck if you have set a machine key in your web.config which also should be the same across your web servers. Also, do you have any security software being active? Did you try different browserw?
Another question for you, why don't you use the membership provider which is introduced with ASP.NET 2. It is flexible and the save password feature is a "built-in".
Regards
|
|
|
|

|
i use the membership provider but i must have add 2 textbox because i use the username to load informations in the session (in the code c#) otherwise (without my textbox but with textbox of asp:login), i don't have recover the login: asp: <asp:Login ID="UserLoginCtrl"...
c#: UserLoginCtrl.UserName is always empty.(I surely do something wrong). I'd like to use the component more simply but i can not...
Regarding my first problem i ve tried with firefox and i ve no problem...
|
|
|
|

|
the 2 textboxes are in component it's just a breaking down into <template> but without this breaking down, i don't recover my data. in this case the gestion is not hidden and i must do manually (gestion of cookies). I hope that it's clear enough
thanks
|
|
|
|

|
Adam:
I get a CS0246: The type or namespace name 'InvalidCypherTextException' could not be found (are you missing a using directive or an assembly reference?)
... error at: throw new InvalidCypherTextException("Unable to decode the text", ex.InnerException);
I cannot find this exception in any of the .Net docs. The closest I come up with is a InvalidCipherTextException() in BouncyCastle. Where in .Net is this exception defined? I'm not sure what namespace in use.
Thanks
Kurt
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Discussing how to encode and tamper-proof text and cookies using the MachineKey, by using reflection.
| Type | Article |
| Licence | Ms-PL |
| First Posted | 3 Apr 2006 |
| Views | 153,376 |
| Bookmarked | 108 times |
|
|