제목에서 알 수 있듯이 다음과 같은 결과를 얻었습니다.
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은 다음과 같습니다.
아래 링크를 클릭하거나 브라우저에 붙여 넣어 이메일 계정을 확인하십시오.
받는 쪽에서 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=value
가 value
포함되어 있을 때 문제가 있습니다 =
(일부는 삭제되지만 정확한 동작은 기억 나지 않습니다). =
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);