基64字符数组的无效长度

时间:2021-12-13 14:35:10

As the title says, I am getting:

正如题目所说,我得到:

Invalid length for a Base-64 char array.

基64字符数组的无效长度。

I have read about this problem on here and it seems that the suggestion is to store ViewState in SQL if it is large. I am using a wizard with a good deal of data collection so chances are my ViewState is large. But, before I turn to the "store-in-DB" solution, maybe somebody can take a look and tell me if I have other options?

我在这里读过关于这个问题的文章,似乎建议在SQL中存储ViewState,如果它很大的话。我正在使用一个具有大量数据收集的向导,所以我的ViewState可能很大。但是,在我转向“存储- db”解决方案之前,也许有人可以看看,然后告诉我是否还有其他选择?

I construct the email for delivery using the below method:

我使用以下方法构建邮件发送:

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);
}

The Encrypt method looks like this:

加密方法如下:

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);
}

Here is what the HTML looks like in hotmail:

以下是hotmail中的HTML:

Please click on the link below or paste it into a browser to verify your email account.

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

http://localhost:1563/Accounts/VerifyEmail.aspx?a=YOHY57xYRENEOu3H+FGq1Rf09AZAI56EPjfwuK8XWKg=

http://localhost:1563 /账户/ VerifyEmail.aspx ? = YOHY57xYRENEOu3H + FGq1Rf09AZAI56EPjfwuK8XWKg =

On the receiving end, the VerifyEmail.aspx.cs page has the line:

在接收端,VerifyEmail.aspx。cs页面有一行:

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

Here is the getter for UserNameToVerify:

下面是UserNameToVerify的getter:

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

And here is the GetQueryStringValue method:

这里是GetQueryStringValue方法:

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

And the decrypt method looks like:

解密方法如下:

public static string Decrypt(string cipherText, string password)
{

    **// THE ERROR IS THROWN HERE!!**
    byte[] cipherBytes = Convert.FromBase64String(cipherText);

Can this error be remedied with a code fix or must I store ViewState in the database?

可以用代码修复这个错误,还是必须在数据库中存储ViewState ?

4 个解决方案

#1


135  

The length of a base64 encoded string is always a multiple of 4. If it is not a multiple of 4, then = characters are appended until it is. A query string of the form ?name=value has problems when the value contains = charaters (some of them will be dropped, I don't recall the exact behavior). You may be able to get away with appending the right number of = characters before doing the base64 decode.

base64编码的字符串的长度总是4的倍数。如果它不是4的倍数,那么=字符将被追加到4的倍数。表单?name=value的查询字符串在值包含= charater时出现问题(其中一些将被删除,我不记得确切的行为)。在进行base64解码之前,您可以添加正确的=字符数。

Edit 1

编辑1

You may find that the value of UserNameToVerify has had "+"'s changed to " "'s so you may need to do something like so:

您可能会发现UserNameToVerify的值已经将"+" s改为" " " s,因此您可能需要这样做:

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

This should get the length right;

这个长度应该是对的;

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

Of course calling UrlEncode (as in LukeH's answer) should make this all moot.

当然,调用UrlEncode(正如卢克的回答)会让这一切变得毫无意义。

#2


26  

My guess is that you simply need to URL-encode your Base64 string when you include it in the querystring.

我的猜测是,当您将Base64字符串包含在querystring中时,您只需对其进行url编码。

Base64 encoding uses some characters which must be encoded if they're part of a querystring (namely + and /, and maybe = too). If the string isn't correctly encoded then you won't be able to decode it successfully at the other end, hence the errors.

Base64编码使用一些必须编码的字符,如果它们是querystring的一部分(即+和/,也可能是)。如果字符串没有正确编码,那么您将无法在另一端成功解码,因此会出现错误。

You can use the HttpUtility.UrlEncode method to encode your Base64 string:

您可以使用HttpUtility。UrlEncode方法对Base64字符串进行编码:

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>";

#3


7  

I'm not Reputable enough to upvote or comment yet, but LukeH's answer was spot on for me.

我还没有足够的声誉去支持或者评论,但是卢克的回答对我来说是正确的。

As AES encryption is the standard to use now, it produces a base64 string (at least all the encrypt/decrypt implementations I've seen). This string has a length in multiples of 4 (string.length % 4 = 0)

由于AES加密是现在使用的标准,它生成一个base64字符串(至少是我看到的所有加密/解密实现)。这个字符串的长度是4(字符串)的倍数。长度% 4 = 0)

The strings I was getting contained + and = on the beginning or end, and when you just concatenate that into a URL's querystring, it will look right (for instance, in an email you generate), but when the the link is followed and the .NET page recieves it and puts it into this.Page.Request.QueryString, those special characters will be gone and your string length will not be in a multiple of 4.

琴弦我收到了包含+、=开始或者结束,当你连接到一个URL的查询字符串,它将看起来正确(例如,在一个电子邮件生成),但当跟着和。net页面链接接待它,把它变成this.Page.Request。QueryString,这些特殊字符将消失,您的字符串长度将不会是4的倍数。

As the are special characters at the FRONT of the string (ex: +), as well as = at the end, you can't just add some = to make up the difference as you are altering the cypher text in a way that doesn't match what was actually in the original querystring.

特殊字符在前面的字符串(例:+),以及=结束时,你不能只是添加一些=来弥补差额为你改变密码文本的方式不匹配原始变量实际上是什么。

So, wrapping the cypher text with HttpUtility.URLEncode (not HtmlEncode) transforms the non-alphanumeric characters in a way that ensures .NET parses them back into their original state when it is intepreted into the querystring collection.

因此,将cypher文本包装为HttpUtility。URLEncode(不是HtmlEncode)将非字母数字字符转换成一种确保. net将它们解析回原始状态的方式,当它被集成到querystring集合中时。

The good thing is, we only need to do the URLEncode when generating the querystring for the URL. On the incoming side, it's automatically translated back into the original string value.

好在,我们只需要在为URL生成查询字符串时执行URLEncode。在传入端,它将自动转换回原始字符串值。

Here's some example code

这里有一些示例代码

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

#4


4  

My initial guess without knowing the data would be that the UserNameToVerify is not a multiple of 4 in length. Check out the FromBase64String on msdn.

我在不知道数据的情况下的初步猜测是UserNameToVerify系统长度不是4的倍数。查看msdn上的FromBase64String。

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

#1


135  

The length of a base64 encoded string is always a multiple of 4. If it is not a multiple of 4, then = characters are appended until it is. A query string of the form ?name=value has problems when the value contains = charaters (some of them will be dropped, I don't recall the exact behavior). You may be able to get away with appending the right number of = characters before doing the base64 decode.

base64编码的字符串的长度总是4的倍数。如果它不是4的倍数,那么=字符将被追加到4的倍数。表单?name=value的查询字符串在值包含= charater时出现问题(其中一些将被删除,我不记得确切的行为)。在进行base64解码之前,您可以添加正确的=字符数。

Edit 1

编辑1

You may find that the value of UserNameToVerify has had "+"'s changed to " "'s so you may need to do something like so:

您可能会发现UserNameToVerify的值已经将"+" s改为" " " s,因此您可能需要这样做:

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

This should get the length right;

这个长度应该是对的;

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

Of course calling UrlEncode (as in LukeH's answer) should make this all moot.

当然,调用UrlEncode(正如卢克的回答)会让这一切变得毫无意义。

#2


26  

My guess is that you simply need to URL-encode your Base64 string when you include it in the querystring.

我的猜测是,当您将Base64字符串包含在querystring中时,您只需对其进行url编码。

Base64 encoding uses some characters which must be encoded if they're part of a querystring (namely + and /, and maybe = too). If the string isn't correctly encoded then you won't be able to decode it successfully at the other end, hence the errors.

Base64编码使用一些必须编码的字符,如果它们是querystring的一部分(即+和/,也可能是)。如果字符串没有正确编码,那么您将无法在另一端成功解码,因此会出现错误。

You can use the HttpUtility.UrlEncode method to encode your Base64 string:

您可以使用HttpUtility。UrlEncode方法对Base64字符串进行编码:

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>";

#3


7  

I'm not Reputable enough to upvote or comment yet, but LukeH's answer was spot on for me.

我还没有足够的声誉去支持或者评论,但是卢克的回答对我来说是正确的。

As AES encryption is the standard to use now, it produces a base64 string (at least all the encrypt/decrypt implementations I've seen). This string has a length in multiples of 4 (string.length % 4 = 0)

由于AES加密是现在使用的标准,它生成一个base64字符串(至少是我看到的所有加密/解密实现)。这个字符串的长度是4(字符串)的倍数。长度% 4 = 0)

The strings I was getting contained + and = on the beginning or end, and when you just concatenate that into a URL's querystring, it will look right (for instance, in an email you generate), but when the the link is followed and the .NET page recieves it and puts it into this.Page.Request.QueryString, those special characters will be gone and your string length will not be in a multiple of 4.

琴弦我收到了包含+、=开始或者结束,当你连接到一个URL的查询字符串,它将看起来正确(例如,在一个电子邮件生成),但当跟着和。net页面链接接待它,把它变成this.Page.Request。QueryString,这些特殊字符将消失,您的字符串长度将不会是4的倍数。

As the are special characters at the FRONT of the string (ex: +), as well as = at the end, you can't just add some = to make up the difference as you are altering the cypher text in a way that doesn't match what was actually in the original querystring.

特殊字符在前面的字符串(例:+),以及=结束时,你不能只是添加一些=来弥补差额为你改变密码文本的方式不匹配原始变量实际上是什么。

So, wrapping the cypher text with HttpUtility.URLEncode (not HtmlEncode) transforms the non-alphanumeric characters in a way that ensures .NET parses them back into their original state when it is intepreted into the querystring collection.

因此,将cypher文本包装为HttpUtility。URLEncode(不是HtmlEncode)将非字母数字字符转换成一种确保. net将它们解析回原始状态的方式,当它被集成到querystring集合中时。

The good thing is, we only need to do the URLEncode when generating the querystring for the URL. On the incoming side, it's automatically translated back into the original string value.

好在,我们只需要在为URL生成查询字符串时执行URLEncode。在传入端,它将自动转换回原始字符串值。

Here's some example code

这里有一些示例代码

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

#4


4  

My initial guess without knowing the data would be that the UserNameToVerify is not a multiple of 4 in length. Check out the FromBase64String on msdn.

我在不知道数据的情况下的初步猜测是UserNameToVerify系统长度不是4的倍数。查看msdn上的FromBase64String。

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