[c#] 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로 변경 되었음을 " "알 수 있으므로 다음과 같이해야 할 수 있습니다.

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

길이가 정확해야합니다.

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

물론 전화 UrlEncode(LukeH의 답변에서와 같이)는이 모든 문제를 해결해야합니다.


답변

내 생각 엔 쿼리 문자열에 포함시킬 때 Base64 문자열 을 URL 인코딩 하기 만하면 됩니다.

Base64 인코딩은 쿼리 문자열의 일부인 경우 인코딩해야하는 일부 문자를 사용합니다 (예 : +/, 그리고 가능할 수도 있음 =). 문자열이 올바르게 인코딩되지 않으면 다른 쪽 끝에서 성공적으로 디코딩 할 수 없으므로 오류가 발생합니다.

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


답변

나는 아직 찬성하거나 댓글을 달기에 충분히 평판이 좋지 않지만 LukeH의 대답은 나를 위해 자리를 잡았습니다.

AES 암호화는 현재 사용하는 표준이므로 base64 문자열을 생성합니다 (적어도 내가 본 모든 암호화 / 복호화 구현). 이 문자열의 길이는 4의 배수입니다 (string.length % 4 = 0).

내가 포함 된 문자열은 시작 또는 끝 부분에 + 및 =를 포함하고 있으며 URL의 쿼리 문자열에 연결하면 올바르게 표시되지만 (예 : 생성 한 이메일에서) 링크를 따라갈 때 .NET 페이지는 그것을 받아 this.Page.Request.QueryString에 넣습니다. 특수 문자는 사라지고 문자열 길이는 4의 배수가 아닙니다.

문자열의 FRONT에 특수 문자 (예 : +)가 있고 끝에 =가 있으므로 암호 텍스트를 변경하는 방식으로 차이를 보완하기 위해 =를 추가 할 수 없습니다. 원래 쿼리 문자열에 실제로 있던 것과 일치하지 않습니다.

따라서 암호 텍스트를 HttpUtility.URLEncode (HtmlEncode가 아님)로 래핑하면 .NET이 쿼리 문자열 컬렉션으로 해석 될 때 원래 상태로 다시 구문 분석하는 방식으로 영숫자가 아닌 문자를 변환합니다.

좋은 점은 URL에 대한 쿼리 문자열을 생성 할 때만 URLEncode를 수행하면된다는 것입니다. 들어오는 쪽에서는 자동으로 원래 문자열 값으로 다시 변환됩니다.

다음은 몇 가지 예제 코드입니다.

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


답변

암호화 된 문자열에는 두 개의 특수 문자 +=.

‘+’기호가 오류를 발생 시켰으므로 아래 솔루션이 잘 작동했습니다.

//replace + sign

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

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

또는

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


답변