2010-01-22 10 views
15

मुझे पता है कि इस पर अन्य प्रश्न पूछे गए हैं लेकिन अब तक कोई भी समाधान प्रदान नहीं कर रहा है या मेरे पास बिल्कुल समस्या है।रिजेंडेल प्रबंधित "पैडिंग अमान्य है और इसे हटाया नहीं जा सकता" जो केवल तब होता है जब उत्पादन में डिक्रिप्टिंग

नीचे दी गई कक्षा स्ट्रिंग के एन्क्रिप्शन और डिक्रिप्शन को संभालती है, कुंजी और वेक्टर पास में हमेशा समान होते हैं।

स्ट्रिंग्स एन्क्रिप्टेड और डिक्रिप्ट किए गए स्ट्रिंग हमेशा संख्याएं होती हैं, अधिकतर काम करते हैं लेकिन कभी-कभी डिक्रिप्ट करने पर कभी-कभी विफल रहता है (लेकिन केवल उत्पादन सर्वर पर)। मुझे जिक्र करना चाहिए कि स्थानीय और उत्पादन वातावरण दोनों विंडोज सर्वर 2003 पर आईआईएस 6 में हैं, जो क्लास का उपयोग करता है वह कोड .ashx हैंडलर में बैठता है। उदाहरण है कि उत्पादन सर्वर पर विफल रहता है "0000232668"

त्रुटि संदेश

System.Security.Cryptography.CryptographicException है: पैडिंग अमान्य है और हटाया नहीं जा सकता। System.Security.Cryptography.RijndaelManagedTransform.DecryptData पर (बाइट [] inputBuffer, Int32 inputOffset, Int32 inputCount, बाइट [] & outputBuffer, Int32 outputOffset, PaddingMode paddingMode, बूलियन flast)

और कोड

public class Aes 
    { 
     private byte[] Key; 
     private byte[] Vector; 

     private ICryptoTransform EncryptorTransform, DecryptorTransform; 
     private System.Text.UTF8Encoding UTFEncoder; 

     public Aes(byte[] key, byte[] vector) 
     { 
      this.Key = key; 
      this.Vector = vector; 

      // our encyption method 
      RijndaelManaged rm = new RijndaelManaged(); 

      rm.Padding = PaddingMode.PKCS7; 

      // create an encryptor and decyptor using encryption method. key and vector 
      EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector); 
      DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector); 

      // used to translate bytes to text and vice versa 
      UTFEncoder = new System.Text.UTF8Encoding(); 
     } 

     /// Encrypt some text and return a string suitable for passing in a URL. 
     public string EncryptToString(string TextValue) 
     { 
      return ByteArrToString(Encrypt(TextValue)); 
     } 

     /// Encrypt some text and return an encrypted byte array. 
     public byte[] Encrypt(string TextValue) 
     { 
      //Translates our text value into a byte array. 
      Byte[] bytes = UTFEncoder.GetBytes(TextValue); 
      Byte[] encrypted = null; 

      //Used to stream the data in and out of the CryptoStream. 
      using (MemoryStream memoryStream = new MemoryStream()) 
      {     
       using (CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write)) 
       { 
        cs.Write(bytes, 0, bytes.Length);      
       } 

       encrypted = memoryStream.ToArray();     
      } 

      return encrypted; 
     } 

     /// The other side: Decryption methods 
     public string DecryptString(string EncryptedString) 
     { 
      return Decrypt(StrToByteArray(EncryptedString)); 
     } 

     /// Decryption when working with byte arrays.  
     public string Decrypt(byte[] EncryptedValue) 
     { 
      Byte[] decryptedBytes = null; 

      using (MemoryStream encryptedStream = new MemoryStream()) 
      { 
       using (CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write)) 
       { 
        decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length); 
       } 

       decryptedBytes = encryptedStream.ToArray(); 
      } 

      return UTFEncoder.GetString(decryptedBytes); 
     } 

     /// Convert a string to a byte array. NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so). 
     //  System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); 
     //  return encoding.GetBytes(str); 
     // However, this results in character values that cannot be passed in a URL. So, instead, I just 
     // lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100). 
     public byte[] StrToByteArray(string str) 
     { 
      if (str.Length == 0) 
       throw new Exception("Invalid string value in StrToByteArray"); 

      byte val; 
      byte[] byteArr = new byte[str.Length/3]; 
      int i = 0; 
      int j = 0; 
      do 
      { 
       val = byte.Parse(str.Substring(i, 3)); 
       byteArr[j++] = val; 
       i += 3; 
      } 
      while (i < str.Length); 
      return byteArr; 
     } 

     // Same comment as above. Normally the conversion would use an ASCII encoding in the other direction: 
     //  System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 
     //  return enc.GetString(byteArr);  
     public string ByteArrToString(byte[] byteArr) 
     { 
      byte val; 
      string tempStr = ""; 
      for (int i = 0; i <= byteArr.GetUpperBound(0); i++) 
      { 
       val = byteArr[i]; 
       if (val < (byte)10) 
        tempStr += "00" + val.ToString(); 
       else if (val < (byte)100) 
        tempStr += "0" + val.ToString(); 
       else 
        tempStr += val.ToString(); 
      } 
      return tempStr; 
     } 
के लिए

संपादित करें: आपकी सभी मदद के लिए धन्यवाद, हालांकि आपके उत्तरों ने समस्या को अनदेखा नहीं किया, जो कुछ बेवकूफ सरल साबित हुआ। मैं एक सर्वर पर एक एन्क्रिप्टेड स्ट्रिंग उत्पन्न कर रहा था और इसे किसी अन्य सर्वर पर डिक्रिप्शन और प्रसंस्करण के लिए एक हैंडलर पर सौंप रहा था, लेकिन यह पता चला है कि विभिन्न सर्वरों पर चलने पर एन्क्रिप्शन के परिणाम अलग-अलग होते हैं, इसलिए प्राप्तकर्ता सर्वर इसे डिक्रिप्ट नहीं कर सका। दुर्घटनाओं से इस पर संकेतों में से एक ने ठोकर खाई, इसलिए मैंने इसे

उत्तर

11

कभी-कभी आपको अमान्य पैडिंग के बारे में एक संदेश प्राप्त होगा जब किसी भी कारण से एन्क्रिप्शन और डिक्रिप्शन एक ही कुंजी या प्रारंभिक वेक्टर का उपयोग नहीं किया है। पैडिंग आपके सादे टेक्स्ट के अंत में जोड़े गए कई बाइट्स हैं जो इसे सिफर के लिए काम करने के लिए पूर्ण संख्या में ब्लॉक तक बनाते हैं। पीकेसीएस 7 में प्रत्येक बाइट पैडिंग बाइट्स की संख्या के बराबर है, इसलिए इसे हमेशा डिक्रिप्शन के बाद हटाया जा सकता है। आपके डिक्रिप्शन ने एक स्ट्रिंग का नेतृत्व किया है जहां अंतिम n बाइट्स अंतिम बाइट के मूल्य n के बराबर नहीं हैं (उम्मीद है कि वाक्य समझ में आता है)। तो मैं आपकी सभी चाबियों को दोबारा जांच दूंगा।

वैकल्पिक रूप से, आपके मामले में, मैं यह सुनिश्चित करने का सुझाव दूंगा कि आप प्रत्येक एन्क्रिप्शन और डिक्रिप्शन ऑपरेशन के लिए RijndaelManagedTransform का उदाहरण बनाएं और निपटें, इसे कुंजी और वेक्टर के साथ प्रारंभ करना। यह समस्या इस ट्रांसफॉर्म ऑब्जेक्ट का पुन: उपयोग करके बहुत अच्छी तरह से हो सकती है, जिसका अर्थ है कि पहले उपयोग के बाद, यह सही प्रारंभिक स्थिति में नहीं है।

+0

एरर हाँ टिप्पणियों के बारे में खेद है, यह एनोथ एसओ सवाल से "उधार कोड" है। "यह कहां से आया" स्ट्रिंग या कोड? –

+0

स्ट्रिंग। खुशी है कि यह उधार लिया गया कोड है, मुझे सावधानी से चलने की ज़रूरत नहीं है ... –

+0

यदि यह मामला है तो यह स्थानीय पर्यावरण में क्यों काम करेगा? आपके उत्तर पर सवाल नहीं उठाते, बस अजीब लगता है –

2

चरित्र मूल्यों में इस परिणाम है कि एक यूआरएल

में पारित नहीं किया जा सकता कारण है कि आप अपने स्वयं के एन्कोडिंग, StrToByteArray उपयोग कर रहे हैं Base64 एन्कोडिंग के बजाय है? एक बहुत बेहतर

public string EncryptToString(string TextValue) 
{ 
    return Convert.ToBase64String(Encrypt(TextValue)); 
} 

public string DecryptToString(string TextValue) 
{ 
    return Decrypt(Convert.FromBase64String(TextValue)); 
} 

तो चीजें काम करना चाहिए:

आप ये परिवर्तन कर सकते हैं।

संपादित करें:
ToBase64String और QueryString के साथ समस्या के बारे में:
आप अपने खुद के QueryString तो पार्स करने क्या आप वाकई केवल पहली = -sign पर विभाजित करने की जरूरत है, तो।

var myURL = "http://somewhere.com/default.aspx?encryptedID=s9W/h7Sls98sqw==&someKey=someValue"; 
var myQS = myURL.SubString(myURL.IndexOf("?") + 1); 
var myKVPs = myQS.Split("&"); 
foreach (var kvp in myKVPs) { 
    // It is important you specify a maximum number of 2 elements 
    // since the Base64 encoded string might contain =-signs. 
    var keyValue = kvp.Split("=", 2); 
    var key = keyValue[0]; 
    var value = keyValue[1]; 
    if (key == "encryptedID") 
    var decryptedID = myAES.DecryptToString(value); 
} 

इस तरह आपको बेस 64 एन्कोड किए जाने पर आपके क्वेरीस्ट्रिंग में किसी भी वर्ण को प्रतिस्थापित करने की आवश्यकता नहीं है।

+0

इसकी वजह यह है कि मुझे एन्क्रिप्टेड स्ट्रिंग को क्वेरीस्ट्रिंग पैरामीटर के रूप में पास करने की आवश्यकता है। मैं ToBase64String उपयोग कर रहा था और स्ट्रिंग कर पात्रों पर की जगह "/", "=", और एक दूसरे को जो मुझे पल में निकल जाता है, लंबे समय से संख्या स्वरूप सरल –

+0

लग रहा था जब परिणाम का उपयोग कर किसी भी प्रतिस्थापन क्या करने की जरूरत नहीं होनी चाहिए एक क्वेरीस्ट्रिंग में। मैं कई वर्षों तक क्वेरीबिंग में किसी भी समस्या के बिना ToBase64String का उपयोग कर रहा हूं। –

+0

उम्म मैं आप कैसे दे सकते हैं और =, + या/मूल्यों querystring में पात्रों और यूआरएल –

12

मैं इसे बंद करने से पहले क्रिप्टोस्ट्रीम पर FlushFinalBlock विधि को स्पष्ट रूप से कॉल करता हूं। यही कारण है कि अपने एन्क्रिप्ट विधि में निम्न कार्य का मतलब होगा:

using (CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write)) 
{ 
    cs.Write(bytes, 0, bytes.Length); 
    cs.FlushFinalBlock();   
} 

यदि आप ऐसा नहीं करते हैं, तो यह हो सकता है कि एन्क्रिप्टेड डेटा छोटा किया जा रहा है - यह एक "अमान्य गद्दी" परिदृश्य में परिणाम होगा। पीकेसीएस 7 का उपयोग करते समय पैडिंग हमेशा मौजूद होती है, भले ही डेटा एन्क्रिप्टेड किया गया हो, सिफर की ब्लॉक लंबाई से गठबंधन किया गया हो।

+1

FlushFinalBlock() जब CryptoStream निपटान किया जाता है कहा जाता है, जो एक का उपयोग कर बयान –

+1

साथ अपने आप होता है हो सकता है कि वे कहते हैं कि दोष तय है, लेकिन यह निश्चित रूप से एक बार ऐसा होता है कि CryptoStream.Dispose FlushFinalBlock फोन नहीं किया था! http://bytes.com/topic/c-sharp/answers/255847-encrypt-string-string-vice-versa –

+0

जैसे वे उस में .NET 2.0 तय लग रहा है, लेकिन मैं निश्चित रूप निस्तब्धता की आदत के लिए हो रही करने का सुझाव देते हैं अंतिम खुद को ब्लॉक करें। –

संबंधित मुद्दे

 संबंधित मुद्दे