code

Base-64 char 배열의 길이가 잘못되었습니다.

codestyles 2020. 10. 11. 10:35
반응형

Base-64 char 배열의 길이가 잘못되었습니다.


제목에서 알 수 있듯이 다음을 얻습니다.

Base-64 char 배열의 길이가 잘못되었습니다.

이 문제에 대해 여기에서 읽었으며 ViewState가 큰 경우 SQL에 저장하는 것이 좋습니다. 데이터 수집이 많은 마법사를 사용하고 있으므로 ViewState가 클 가능성이 큽니다. 그러나 "DB에 저장"솔루션으로 전환하기 전에 누군가가 다른 옵션이 있는지 살펴보고 알려줄 수 있습니까?

아래 방법을 사용하여 배송 용 이메일을 구성합니다.

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

Encrypt 메서드는 다음과 같습니다.

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은 다음과 같습니다.

아래 링크를 클릭하거나 브라우저에 붙여 넣어 이메일 계정을 확인하십시오.

http : // localhost : 1563 / Accounts / VerifyEmail.aspx? a = 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로 인코딩 된 문자열의 길이는 항상 4의 배수입니다. 4의 배수가 아닌 경우 =문자가 추가 될 때까지 추가됩니다. 형식의 쿼리 문자열 에는 문자 ?name=valuevalue포함되어 있을 때 문제가 있습니다 =(일부는 삭제되지만 정확한 동작은 기억 나지 않습니다). =base64 디코딩을 수행하기 전에 올바른 수의 문자 를 추가하지 않아도 될 수 있습니다 .

편집 1

당신의 가치 것을 알 수 있습니다 UserNameToVerify했다가 "+"'로 변경 s는 " "당신과 같이 일을해야 할 수 있도록 S'

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

길이가 정확해야합니다.

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.


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

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.

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

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

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)

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.

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.

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.

Here's some example code

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

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.

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

The encrypted string had two special characters, + and =.

'+' sign was giving the error, so below solution worked well:

//replace + sign

encryted_string = encryted_string.Replace("+", "%2b");

//`%2b` is HTTP encoded string for **+** sign

OR

//encode special charactes 

encryted_string = HttpUtility.UrlEncode(encryted_string);

//then pass it to the decryption process
...

    string stringToDecrypt = CypherText.Replace(" ", "+");
    int len = stringToDecrypt.Length;
    byte[] inputByteArray = Convert.FromBase64String(stringToDecrypt); 

참고URL : https://stackoverflow.com/questions/2925729/invalid-length-for-a-base-64-char-array

반응형