बेस -64 चार सरणी के लिए अमान्य लंबाई


91

जैसा कि शीर्षक कहता है, मुझे मिल रहा है:

बेस -64 चार सरणी के लिए अमान्य लंबाई।

मैंने इस समस्या के बारे में यहाँ पढ़ा है और ऐसा लगता है कि यह सुझाव एसक्यूएल में ViewState को स्टोर करने के लिए है यदि यह बड़ा है। मैं डेटा संग्रह की एक अच्छी डील के साथ एक विज़ार्ड का उपयोग कर रहा हूं, इसलिए संभावना है कि मेरा व्यूस्टेट बड़ा है। लेकिन, इससे पहले कि मैं "स्टोर-इन-डीबी" समाधान की ओर मुड़ूं, शायद कोई देख ले और मुझे बताए कि क्या मेरे पास अन्य विकल्प हैं?

मैं नीचे विधि का उपयोग करके डिलीवरी के लिए ईमेल का निर्माण करता हूं:

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

एन्क्रिप्ट विधि इस प्रकार है:

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 / लेखा / VerifyEmail.aspx एक = 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 को स्टोर करना चाहिए?

जवाबों:


205

एक बेस 64 एन्कोडेड स्ट्रिंग की लंबाई हमेशा 4 से अधिक होती है। यदि यह 4 से अधिक नहीं है, तो =पात्रों को तब तक जोड़ा जाता है जब तक कि यह न हो। प्रपत्र के क्वेरी स्ट्रिंग ?name=valueमें समस्याएँ होती हैं जब वर्णक valueहोते हैं =(उनमें से कुछ को छोड़ दिया जाएगा, मुझे सटीक व्यवहार याद नहीं है)। =बेस 64 डिकोड करने से पहले आप सही संख्या में वर्णों को जोड़कर दूर जा सकते हैं।

संपादित करें 1

हो सकता है कि का मान UserNameToVerifyकर चुके हैं "+"'में बदल रहा है " "s' तो तुम इतनी तरह कुछ करने के लिए आवश्यकता हो सकती है:

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

यह लंबाई सही होनी चाहिए;

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

बेशक UrlEncode(ल्यूक के जवाब के रूप में) कॉलिंग यह सब लूट करना चाहिए।


9
धन्यवाद ब्रैड - यह वास्तव में कोड का यह थोड़ा सा था जिसने काम किया: a = a.Replace ("", "+");
पीटर

1
@ कोड शेरपा: अगर ऐसा है, तो आपका सबसे अच्छा विकल्प स्ट्रिंग भेजने से पहले urlencode है, और रसीद में urldecode। अन्यथा यदि एक और यूआरएल महत्वपूर्ण चरित्र आपके स्ट्रिंग में हो जाता है तो आपको एक और Replaceबयान जोड़ना होगा । एनकोडिंग एक आवरण है जो आपकी परवाह किए बिना बचाता है।
मैट एलेन

5
आप रसीद पर अपने स्ट्रिंग को UrlDecode नहीं करते हैं क्योंकि अनुरोध पैरामीटर पहले से ही ASP.Net द्वारा UrlDecoded हैं। हालांकि आपको भेजते समय UrlEncode चाहिए।
प्रात:

या यदि आप एक इनलाइन संस्करण चाहते हैं a = a + new string('=', (4 - a.Length % 4) % 4):। RFC 4648 URL-safe 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

1
"आप UrlD timecode करने के लिए नहीं है" - यह! मेरे कोड के माध्यम से कदम रखते हुए मैं देख सकता था कि पैरामीटर पहले से ही डिकोड हो गया था, समस्या मुझे यह चल रही थी जिसके माध्यम से UrlDecodeपात्रों को निकालना था। साभार @MattEllen
GJKH

30

मेरा अनुमान है कि आपको बस URL-एनकोड की जरूरत है जब आप इसे क्वेरिस्ट्रिंग में शामिल करते हैं, तो अपने बेस 64 स्ट्रिंग को करना होगा।

Base64 एन्कोडिंग कुछ वर्णों का उपयोग करता है जिन्हें एन्कोडेड होना चाहिए (यदि +और /, और शायद यह =भी)। यदि स्ट्रिंग सही ढंग से एन्कोडेड नहीं है, तो आप इसे दूसरे छोर पर सफलतापूर्वक डिकोड नहीं कर पाएंगे, इसलिए त्रुटियां।

आप HttpUtility.UrlEncodeअपने बेस 64 स्ट्रिंग को एनकोड करने के लिए विधि का उपयोग कर सकते हैं :

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

धन्यवाद। बस अपने सुझाव ल्यूक की कोशिश की, लेकिन वह काम नहीं किया :(।
पीटर

@ शेरपा - इसे काम करते रहो, समस्या लगभग निश्चित रूप से अनुगामी =पात्रों के साथ है।

ल्यूक - मुझे लग रहा है कि तुम सही हो। घर पर यह कोशिश करेंगे। ढेरों धन्यवाद। FYI करें - मैंने जोड़ा कि स्ट्रिंग मेरे मूल पोस्ट में मेरे हॉटमेल इनबॉक्स में कैसी दिखती है।
पीटर

चाचा ब्रैड सही है, मेरे पास पिछले हफ्ते एक ही मुद्दा था और समस्या एक "=" चरित्र थी ।_।
मार्कोटे

10

मैं अभी तक प्रतिष्ठा या टिप्पणी करने के लिए पर्याप्त नहीं हूं, लेकिन ल्यूक का जवाब मेरे लिए हाजिर था।

जैसा कि एईएस एन्क्रिप्शन अब उपयोग करने के लिए मानक है, यह एक बेस 64 स्ट्रिंग (कम से कम सभी एन्क्रिप्ट / डिक्रिप्शन कार्यान्वयन मैंने देखा है) का उत्पादन करता है। इस स्ट्रिंग की लंबाई 4 के गुणकों में होती है (string.length% 4 = 0)

जो तार मैं शुरुआत और अंत में + और = समाहित कर रहा था, और जब आप इसे केवल एक URL के क्वेरिस्टिंग में समाहित करते हैं, तो यह सही लगेगा (उदाहरण के लिए, आपके द्वारा उत्पन्न ईमेल में), लेकिन जब लिंक का पालन किया जाता है और .NET पेज इसे रिक्रिएट करता है और इसे इसमें डालता है। Page.Request.QueryString, उन विशेष वर्णों को हटा दिया जाएगा और आपकी स्ट्रिंग की लंबाई 4 से अधिक नहीं होगी।

जैसे कि स्ट्रिंग के पूर्व (पूर्व: +) पर विशेष वर्ण हैं, साथ ही साथ = अंत में, आप अंतर जोड़ने के लिए कुछ = कुछ जोड़ नहीं सकते क्योंकि आप साइबर पाठ को एक तरह से बदल रहे हैं। टी क्या वास्तव में मूल querystring में मैच था।

इसलिए, साइबर टेक्स्ट को HttpUtility.URLEncode (HtmlEncode के साथ नहीं) में लपेटकर गैर-अल्फ़ान्यूमेरिक वर्णों को एक तरह से रूपांतरित करता है। यह सुनिश्चित करता है कि .NET उन्हें क्वेरिस्ट्रिंग संग्रह में शामिल होने पर वापस उनकी मूल स्थिति में भेज देता है।

अच्छी बात यह है कि हमें केवल URL के लिए querystring जेनरेट करते समय 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। मैं उस पर एक नज़र डालूँगा। मैंने अपने मूल पोस्ट (FYI) में UserNameToVeryify पोस्ट किया। ठीक है ... अब मुझे वास्तव में जाने की जरूरत है या मैं असली मालिक के साथ मुसीबत में पड़ने जा रहा हूँ :)
पीटर

ऐसा लगता है कि इस पोस्ट के रूप में अच्छी तरह से मदद कर सकता है: stackoverflow.com/questions/1392970/…
SwDevMan81

1

एन्क्रिप्ट किए गए स्ट्रिंग में दो विशेष वर्ण थे, +और=

'+' संकेत त्रुटि दे रहा था, इसलिए नीचे दिए गए समाधान ने अच्छी तरह से काम किया:

//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); 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.