Base-64字符数组的长度无效

正如标题所说,我得到:

Base-64字符数组的长度无效。

我已经读过关于这个问题在这里,似乎build议是存储ViewState在SQL中,如果它很大。 我正在使用一个有很多数据收集的向导,所以我的ViewSate很大。 但是,在谈到“数据库存储”解决scheme之前,也许有人可以看看,告诉我是否有其他select?

我使用下面的方法构build邮件发送:

public void SendEmailAddressVerificationEmail(string userName, string to) { string msg = "Please click on the link below or paste it into a browser to verify your email account.<BR><BR>" + "<a href=\"" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + userName.Encrypt("verify") + "\">" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + userName.Encrypt("verify") + "</a>"; SendEmail(to, "", "", "Account created! Email verification required.", msg); } 

encryption方法如下所示:

 public static string Encrypt(string clearText, string Password) { byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText); PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16)); return Convert.ToBase64String(encryptedData); } 

这里是HTML在hotmail中的样子:

请点击下面的链接或粘贴到浏览器来validation您的电子邮件帐户。

HTTP://本地主机:1563 /账户/ VerifyEmail.aspx一个= YOHY57xYRENEOu3H + FGq1Rf09AZAI56EPjfwuK8XWKg =

在接收端,VerifyEmail.aspx.cs页面包含以下行:

  string username = Cryptography.Decrypt(_webContext.UserNameToVerify, "verify"); 

这里是UserNameToVerify的getter:

 public string UserNameToVerify { get { return GetQueryStringValue("a").ToString(); } } 

这里是GetQueryStringValue方法:

 private static string GetQueryStringValue(string key) { return HttpContext.Current.Request.QueryString.Get(key); } 

解密方法如下所示:

  public static string Decrypt(string cipherText, string password) { **// THE ERROR IS THROWN HERE!!** byte[] cipherBytes = Convert.FromBase64String(cipherText); 

这个错误可以通过代码修复来解决吗?还是必须将ViewState存储在数据库中?

提前致谢。

base64编码的string的长度总是4的倍数。如果它不是4的倍数,那么=字符被追加,直到它为止。 当value包含= charaters(其中一些将被删除,我不记得确切的行为)时,forms?name=value的查询string有问题。 在进行base64解码之前,您可能能够附加正确数量的=字符。

编辑1

您可能会发现UserNameToVerify的值已将“+”更改为“”,因此您可能需要这样做;

 a = a.Replace(" ","+"); 

这应该得到正确的长度;

 int mod4 = a.Length % 4; if ( mod4 > 0 ) { a += new string( '=', 4 - mod4 ); } 

当然,调用UrlEncode(如LukeH的答案)应该使这一切都没有实际意义。

我的猜测是,只要在将查询string中包含Base64string时,就需要对其进行url编码 。

Base64编码使用一些必须被编码的字符,如果它们是查询string的一部分(即+/ ,也许=也是)。 如果string没有正确编码,那么你将无法在另一端成功解码,因此错误。

您可以使用HttpUtility.UrlEncode方法来编码您的Base64string:

 string msg = "Please click on the link below or paste it into a browser " + "to verify your email account.<br /><br /><a href=\"" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "\">" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "</a>"; 

我没有足够的知名度或评论,但LukeH的答案是适合我的。

由于AESencryption是现在使用的标准,它产生一个base64string(至less所有我见过的encryption/解密实现)。 这个string的长度是4的倍数(string.length%4 = 0)

我得到的string包含+和=开头或结尾,当你把它连接到一个URL的查询string,它会看起来是正确的(例如,在你生成的电子邮件),但是当链接被跟随, .NET页面接收并将其放入this.Page.Request.QueryString,那些特殊字符将会消失,您的string长度将不会是4的倍数。

由于string的前面是特殊字符(例如:+),以及末尾的特殊字符,所以不能只添加一些=来弥补差异,因为正在改变密码文本的方式不匹配原来查询string中的内容。

因此,使用HttpUtility.URLEncode(而不是HtmlEncode)封装密码文本会以一种方式转换非字母数字字符,这样可以确保.NET在parsingstring集合中进行parsing时,可以将其parsing为原始状态。

好的是,在为URL生成查询string时,我们只需要执行URLEncode。 在传入方面,它会自动转换回原来的string值。

这是一些示例代码

 string cryptostring = MyAESEncrypt(MySecretString); string URL = WebFunctions.ToAbsoluteUrl("~/ResetPassword.aspx?RPC=" + HttpUtility.UrlEncode(cryptostring)); 

我不知道数据的初步猜测是UserNameToVerify不是4的倍数。 看看msdn上的FromBase64String 。

  // Ok byte[] b1 = Convert.FromBase64String("CoolDude"); // Exception byte[] b2 = Convert.FromBase64String("MyMan");