Base-64文字配列の長さが無効です


93

タイトルが言うように、私は得ています:

Base-64文字配列の長さが無効です。

私はここでこの問題について読みましたが、ViewStateが大きい場合はSQLに保存することをお勧めしているようです。大量のデータ収集を伴うウィザードを使用しているため、ViewStateが大きい可能性があります。しかし、「store-in-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);
}

hotmailでのHTMLの外観は次のとおりです。

以下のリンクをクリックするか、ブラウザに貼り付けて、メールアカウントを確認してください。

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

受信側では、VerifyEmail.aspx.csページに次の行があります。

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

UserNameToVerifyのゲッターは次のとおりです。

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をデータベースに保存する必要がありますか?

回答:


209

base64でエンコードされた文字列の長さは、常に4の倍数です。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の答えのように)電話をかけると、これはすべて無意味になるはずです。


9
ありがとうブラッド-実際に仕事をしたのはこの小さなコードでした:a = a.Replace( ""、 "+");
ピーター

1
@Code Sherpa:その場合は、文字列を送信する前にurlencodeを実行し、受信時にurldecodeを実行するのが最善の選択です。そうしないと、別のURLの重要な文字が文字列に含まれる場合、別のReplaceステートメントを追加する必要があります。エンコーディングは、関係なくあなたを保護するカバーオールです。
マットエレン

6
要求パラメーターはASP.Netによって既にUrlDecodedされているため、受信時に文字列をUrlDecodeにしないでください。ただし、送信するときはUrlEncodeを使用する必要があります。
bleeeah 2012年

または、インラインバージョンが必要な場合:a = a + new string('=', (4 - a.Length % 4) % 4)RFC 4648 URLセーフBase64をデコードする例:public string base64urlDecode(string encoded) { return System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(encoded.Replace("_","/").Replace("-","+") + new string('=', (4 - encoded.Length % 4) % 4))); }
gregmac 2015

1
「あなたはUrlDecodeにしないでください」-これ!コードをステップスルーすると、パラメーターが既にデコードされていることUrlDecodeがわかりました。問題は、文字を削除しながら実行することでした。おかげ@MattEllen
GJKH

30

私の推測では、クエリ文字列に含めるときに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>";

ありがとう。ちょうどあなたの提案ルークを試してみましたが、それは仕事:(ませんでした。
ピーター・

@ Sherpa-作業を続けてください=。問題はほぼ確実に末尾の文字にあります。

ルーク-私はあなたが正しいと感じています。家でこれを試してみます。バンドルに感謝します。参考までに-元の投稿のhotmail受信ボックスに文字列がどのように表示されるかを追加しました。
ピーター

ブラッドおじさんは正しいです。先週同じ問題が発生しました。問題は末尾の「=」文字でした。
マルコテ2010年

10

私はまだ賛成やコメントをするほど評判が良くありませんが、LukeHの答えは私にぴったりでした。

AES暗号化は現在使用されている標準であるため、base64文字列を生成します(少なくとも私が見たすべての暗号化/復号化の実装)。この文字列の長さは4の倍数です(string.length%4 = 0)

私が取得していた文字列は、最初または最後に+と=が含まれており、それをURLのクエリ文字列に連結すると(たとえば、生成した電子メールでは)正しく表示されますが、リンクをたどると、 .NETページはそれを受け取り、this.Page.Request.QueryStringに入れます。これらの特殊文字はなくなり、文字列の長さは4の倍数になりません。

文字列の前に特殊文字(例:+)があり、最後に=があるため、暗号文を変更する方法で違いを補うために=を追加することはできません。元のクエリ文字列に実際に含まれていたものと一致しません。

したがって、暗号文をHttpUtility.URLEncode(HtmlEncodeではない)でラップすると、.NETがクエリ文字列コレクションに解釈されたときに、英数字以外の文字が元の状態に解析されるように変換されます。

良い点は、URLのクエリ文字列を生成するときにURLEncodeを実行するだけでよいことです。着信側では、元の文字列値に自動的に変換されます。

これがいくつかのサンプルコードです

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

6

データを知らない私の最初の推測は、UserNameToVerifyの長さが4の倍数ではないということです。msdnのFromBase64Stringを確認してください。

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

SwDevMan81に感謝します。ちょうど今仕事を辞めていますが、今夜遅くにこれを試します。ご協力いただきありがとうございます。
ピーター

いいえ問題、修正は4の倍数である文字列を取得する文字をパッドにないだろう
SwDevMan81

SwDevMan81に改めて感謝します。それを見てみましょう。UserNameToVeryifyを元の投稿(FYI)に投稿しました。OK ...今、私は本当に行く必要がありますか、本当のボスとトラブルを起こすつもりです:)
ピーター

この記事のかもしれないのヘルプのように見えるだけでなく:stackoverflow.com/questions/1392970/...
SwDevMan81

1

暗号化された文字列には、2つの特殊文字+とが含まれていました=

「+」記号がエラーを示していたため、以下のソリューションが適切に機能しました。

//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
...

0
    string stringToDecrypt = CypherText.Replace(" ", "+");
    int len = stringToDecrypt.Length;
    byte[] inputByteArray = Convert.FromBase64String(stringToDecrypt); 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.