1

状況を説明しましょう。私のコードでは、登録後に生成される文字列に変換されたユーザー ID を暗号化しています。暗号化された文字列は、以下のように url パラメーターとして渡されます。

 string ConfirmCode = string.Empty;
Common.Secure.Security mySec = new Common.Secure.Security();
ConfirmCode  = mySec.Encrypt(myMember.MemberID.ToString());

string EmailValidationLink = "<a  href=\'" + pageScheme + "://" + CurrentDomain.HostName + "/Contents/Common/" + "EN" + "/" + CurrentDomain.EmailValidationPage + "?ConfirmCode=" + **UrlEncode(ConfirmCode)** + "\'>Click here to validate your account.</a>";

と:

protected String UrlEncode(String text) 
{ 
  return HttpContext.Current.Server.UrlEncode(text); 
}

UrlEncode を使用して暗号化された文字列を渡していますが、暗号化されたテキストに '+' 記号が含まれている場合に問題が発生します。この '+' 記号は ' ' スペースと見なされるため、復号化中に Format Exception が発生します。

たとえば、暗号化されたテキストがフェッチ中に「S7+5tZzTm0k=」のようなものである場合、+ 記号は「S7 5tZzTm0k=」と見なされ、フォーマット例外が発生します。

私の暗号化と復号化のコードは以下のようなものです

public string Decrypt(string Text)
{
    if (!ENABLED) return Text;
    des.Key = hashmd5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey));
    des.Mode = CipherMode.ECB;
    ICryptoTransform desdencrypt = des.CreateDecryptor();
    Byte[] buff = Convert.FromBase64String(Text);
    return ASCIIEncoding.ASCII.GetString(desdencrypt.TransformFinalBlock(buff, 0, buff.Length));
}

public string Encrypt(string Text)
{
    if (!ENABLED) return Text;
    des.Key = hashmd5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey));
    des.Mode = CipherMode.ECB;
    ICryptoTransform desdencrypt = des.CreateEncryptor();
    ASCIIEncoding MyASCIIEncoding = new ASCIIEncoding();
    Byte[] buff = ASCIIEncoding.ASCII.GetBytes(Text);
    return Convert.ToBase64String(desdencrypt.TransformFinalBlock(buff, 0, buff.Length));
}

私はこれについてグーグルで調べていて、誰もが UrlEncode を使用すると問題が解決すると示唆していますが、私の場合、使用しても問題は解決しませんでした。

これについてどうすればよいか教えてください。

if (Request.QueryString["ConfirmCode"] != null)
            { 
                bool isAccountSuspended;
                isAccountSuspended = AccountManagement.AcountManager.EmailValidationNote(HttpContext.Current.Server.UrlDecode(Request.QueryString["ConfirmCode"]));

                if (!isAccountSuspended)
                {
                    lblMessage.Text = "Your account is already suspended. Please contact customer service.";
                    lblMessage.ForeColor = System.Drawing.Color.Red;
                }
                else
                {
                    lblMessage.Text = "Thank you for verifying your email address. We hope you’ll enjoy playing with us.";
                }
            }

よろしくSrividhya

4

5 に答える 5

1

必須 Using Directive: using System.Security.Cryptography;

Way to encrypt: HttpUtility.UrlEncode(Encrypt(Value));

例: 文字列値=HttpUtility.UrlEncode(暗号化(値));

Way to decrypt: Decrypt(HttpUtility.UrlDecode(value);

private string Encrypt(string clearText)
{
    string EncryptionKey = "MAKV2SPBNsdsI99212";
    byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
    using (Aes encryptor = Aes.Create())
    {
        Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        encryptor.Key = pdb.GetBytes(32);
        encryptor.IV = pdb.GetBytes(16);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
            clearText = Convert.ToBase64String(ms.ToArray());
        }
    }
    return clearText;
}
private string Decrypt(string cipherText)
{
    string EncryptionKey = "MAKV2SPBNsdsI99212";
    cipherText = cipherText.Replace(" ", "+");
    byte[] cipherBytes = Convert.FromBase64String(cipherText);
    using (Aes encryptor = Aes.Create())
    {
        Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        encryptor.Key = pdb.GetBytes(32);
        encryptor.IV = pdb.GetBytes(16);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(cipherBytes, 0, cipherBytes.Length);
                cs.Close();
            }
            cipherText = Encoding.Unicode.GetString(ms.ToArray());
        }
    }
    return cipherText;
}
于 2014-10-29T12:21:09.663 に答える
0

少し見てみるとRequest.QueryString、クエリ文字列に含まれているもののデコードされたバージョンが得られるため、+ を含むバージョンが得られ、それを効果的に再度デコードしているため、間違いが発生します。

行を次のように変更します

isAccountSuspended = AccountManagement.AcountManager.EmailValidationNote(Request.QueryString["ConfirmCode"]);

(つまり、デコードを削除する)と動作するはずです。

于 2012-04-05T10:30:43.327 に答える
0

+のすべての出現を単純にパーセント エンコーディング-に置き換えることができます%2B

UrlEncode(ConfirmCode).Replace("+", "%2B")
于 2012-04-05T09:19:49.467 に答える
0

これは憶測ですがUrlDecode、同じ文字列を 2 回呼び出しているのではないかと思います。

URL の値が であることを示しましたがConfirmCode=S7%2b5tZzTm0k%3d、これは正しいです (%2b は「+」の正しいエンコードです)。

この文字列を 1 回デコードするとS7+b5tZTm0k=、予想どおり が得られます。

「+」は「 」としてデコードされるため、その文字列をデコードすると、 が得られます。S7 b5tZTm0k=これがあなたが見ているものです。

結果の文字列が一度だけデコードされていることを確認するために、デコード ロジックを調べることができます。

于 2012-04-05T10:55:40.663 に答える
0

OK、あなたからのすべてのデータと他のコメントと回答から、論理的な結論は 1 つしかありません。あなたの URL エンコード文字列は 2 回デコードされます。の最初のデコードで がS7%2B5tZzTm0k%3D得られS7+5tZzTm0k=、2 番目のデコードで が得られますS7 5tZzTm0k=。文字列が url で 2 回デコードされている場所を検出するには、慎重にデバッグするだけです。

PSそれを確認する方法として、値を2回エンコードすると、正しくデコードされます。2 回エンコードされた URL 値はS7%252B5tZzTm0k%253D.

于 2012-04-05T09:27:57.923 に答える