2008-08-14 18 views
39

मैं कुछ सरल स्ट्रिंग एन्क्रिप्शन की जरूरत है, तो मैं निम्नलिखित कोड लिखा था (here से "प्रेरणा" के एक महान सौदा के साथ):खराब पासवर्ड क्यों होता है "पैडिंग अमान्य है और इसे हटाया नहीं जा सकता"?

// create and initialize a crypto algorithm 
    private static SymmetricAlgorithm getAlgorithm(string password) { 
     SymmetricAlgorithm algorithm = Rijndael.Create(); 
     Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
      password, new byte[] { 
      0x53,0x6f,0x64,0x69,0x75,0x6d,0x20,    // salty goodness 
      0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65 
     } 
     ); 
     algorithm.Padding = PaddingMode.ISO10126; 
     algorithm.Key = rdb.GetBytes(32); 
     algorithm.IV = rdb.GetBytes(16); 
     return algorithm; 
    } 

    /* 
    * encryptString 
    * provides simple encryption of a string, with a given password 
    */ 
    public static string encryptString(string clearText, string password) { 
     SymmetricAlgorithm algorithm = getAlgorithm(password); 
     byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText); 
     MemoryStream ms = new MemoryStream(); 
     CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write); 
     cs.Write(clearBytes, 0, clearBytes.Length); 
     cs.Close(); 
     return Convert.ToBase64String(ms.ToArray()); 
    } 

    /* 
    * decryptString 
    * provides simple decryption of a string, with a given password 
    */ 
    public static string decryptString(string cipherText, string password) { 
     SymmetricAlgorithm algorithm = getAlgorithm(password); 
     byte[] cipherBytes = Convert.FromBase64String(cipherText); 
     MemoryStream ms = new MemoryStream(); 
     CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write); 
     cs.Write(cipherBytes, 0, cipherBytes.Length); 
     cs.Close();    
     return System.Text.Encoding.Unicode.GetString(ms.ToArray()); 
    } 

कोड ठीक काम करने के लिए, सिवाय इसके कि जब एक गलत के साथ डेटा decrypting प्रकट होता है कुंजी, मुझे एक क्रिप्टोग्राफिक अपवाद मिलता है - "पैडिंग अमान्य है और इसे हटाया नहीं जा सकता" - cs.Close() लाइन पर decryptString में।

उदाहरण कोड:

string password1 = "password"; 
    string password2 = "letmein"; 
    string startClearText = "The quick brown fox jumps over the lazy dog"; 
    string cipherText = encryptString(startClearText, password1); 
    string endClearText = decryptString(cipherText, password2);  // exception thrown 

मेरा प्रश्न है, इस उम्मीद की जा करने के लिए है? मैंने सोचा होगा कि गलत पासवर्ड के साथ डिक्रिप्ट करने से अपवाद के बजाय नॉनसेंस आउटपुट होगा।

+5

इसने मुझे आपकी टिप्पणी के साथ इतना समय बचाया: '"कोड ठीक काम करता प्रतीत होता है, सिवाय इसके कि जब गलत कुंजी के साथ डेटा डिक्रिप्ट किया जाता है' 'i _swore_ मैंने चाबियाँ कॉपी की थीं, लेकिन 2x देखकर मैंने नहीं किया।उम्मीद है कि यह पैडिंग तंत्र या बदलते कोड को देखने से पहले किसी और की मदद करता है। – atconway

उत्तर

26

मिल हालांकि यह पहले से ही उत्तर दिया गया है मुझे लगता है कि यह एक अच्छा विचार व्याख्या करने के लिए किया जाएगा क्यों की उम्मीद है।

आमतौर पर एक पैडिंग योजना लागू होती है क्योंकि अधिकांश क्रिप्टोग्राफ़िक फ़िल्टर अर्थपूर्ण रूप से सुरक्षित नहीं होते हैं और कुछ प्रकार के क्रिप्टोटाक्स को रोकने के लिए नहीं होते हैं। उदाहरण के लिए, आमतौर पर आरएसए में OAEP पैडिंग योजना का उपयोग किया जाता है जो कुछ प्रकार के हमलों को रोकता है (जैसे एक चयनित सादे टेक्स्ट हमला या blinding)।

एक पैडिंग योजना संदेश भेजने से पहले संदेश मीटर में कुछ (आमतौर पर) यादृच्छिक कचरा जोड़ती है। OAEP विधि में, उदाहरण के लिए, दो दैवज्ञ उपयोग किया जाता है (यह एक साधारण व्याख्या है):

  1. मापांक एक यादृच्छिक संख्या के साथ 0 और K0 बिट्स के साथ आप Padd k1 बिट्स के आकार को देखते हुए।
  2. फिर संदेश में कुछ परिवर्तन लागू करके आप गद्देदार संदेश प्राप्त करते हैं जो एन्क्रिप्ट किया जाता है और भेजा जाता है।

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

+0

जॉर्ज, स्पष्टीकरण के लिए धन्यवाद। मैं वर्णित वही व्यवहार देख रहा हूं, जो डेटा डिक्रिप्ट किया गया है वह सही है। क्या मुझे यह अपवाद खाना चाहिए, या (उम्मीद है) कुछ ऐसा है जो मैं गलत तरीके से कर रहा हूं कि मैं सही कर सकता हूं? अपवाद फेंकने पर क्या गलत हो रहा है? मेरे द्वारा पढ़ी गई सभी पोस्ट उन लोगों द्वारा लिखी गई हैं जो अपवाद को दूर करने में अधिक रुचि रखते हैं। मेरे मामले में मैं अपना उपयोग सही होना चाहता हूं :) – stuck

+1

यह ओपी के सवाल का जवाब नहीं देता है, सवाल एक सममित ब्लॉक सिफर रिजेंडेल के बारे में है, आरएसए जैसे असममित सिफर नहीं। एक ब्लॉक सिफर पैडिंग के लिए डेटा को ब्लॉक आकार के एक से अधिक एन्क्रिप्ट करने के लिए जोड़ा जाता है, आमतौर पर पीकेसीएस # 7 (नी पीकेसीएस # 5) का उपयोग करते हुए। इन पैडिंग योजनाओं के साथ यादृच्छिक बाइट ** ** नहीं जोड़ा गया है। ध्यान दें कि पैडिंग आईएसओ 10126 वापस ले लिया गया था और यादृच्छिक बाइट्स ने कोई सुरक्षा नहीं जोड़ा था। जवाब बिंदु पर होगा अगर यह सममित एन्क्रिप्शन पैडिंग से बात की। सुझाव: प्रश्न का उत्तर देने के लिए उत्तर को ठीक करें। ज़ोमग, वरिष्ठ डेवलपर। – zaph

+1

@zaph मैं सामान्य रूप से समझा रहा हूं कि जब आप उपयोग और अमान्य पासवर्ड का डिक्रिप्ट करते हैं तो आपको कचरे के बजाय अमान्य पैडिंग अपवाद क्यों मिलता है। आरएसए सिर्फ एक उदाहरण था, इस्तेमाल की जाने वाली विशिष्ट पैडिंग योजना और उदाहरण थी। यह ओप प्रश्न का उत्तर देता है क्योंकि यह कहता है: हां, यह उम्मीद की जाती है और यहां और क्यों अजीब "पैडिंग" संदर्भ के बारे में स्पष्टीकरण है कि आप केवल तभी समझ सकते हैं जब आप समझते हैं कि पैडिंग योजना क्या है और इसका उपयोग क्यों किया जाता है, लेकिन आपको अगर आप नहीं करते हैं (एन्क्रिप्शन को पैडिंग के साथ क्या करना है ???) –

3

हाँ, यह उम्मीद की जा करने के लिए है, या कम से कम, अपने वास्तव में क्या होता है जब हमारे क्रिप्टो दिनचर्या गैर decryptable डेटा

1

क्रिप्टोस्ट्रीम में कुछ अपठित बाइट्स हो सकते हैं। धारा को पढ़ने से पहले बंद करना मेरे कार्यक्रम में त्रुटि का कारण बन रहा था।

5

यदि आप अपने उपयोग को सही करना चाहते हैं, तो आपको अपने सिफरटेक्स्ट में authentication जोड़ना चाहिए ताकि आप यह सत्यापित कर सकें कि यह सही पासवर्ड है या सिफरटेक्स्ट को संशोधित नहीं किया गया है। ISO10126 का उपयोग कर रहे पैडिंग केवल एक अपवाद फेंक देंगे यदि अंतिम बाइट पैडिंग (0x01-0x10) के लिए 16 मान्य मानों में से एक के रूप में डिक्रिप्ट नहीं करता है। तो आपके पास 1/16 का मौका गलत पासवर्ड के साथ अपवाद फेंकने का मौका नहीं है, जहां आप इसे प्रमाणित करते हैं तो आपके पास यह तय करने का एक निश्चित तरीका है कि आपका डिक्रिप्शन मान्य है या नहीं।

क्रिप्टो एपी का उपयोग करना आसान लगता है, वास्तव में गलतियों को करना आसान है।उदाहरण के लिए आप अपने कुंजी और iv व्युत्पन्न के लिए एक निश्चित नमक का उपयोग करते हैं, जिसका अर्थ है कि एक ही पासवर्ड से एन्क्रिप्टेड प्रत्येक सिफरटेक्स्ट उस कुंजी के साथ IV का पुन: उपयोग करेगा, जो सीबीसी मोड के साथ अर्थपूर्ण सुरक्षा को तोड़ देगा, IV को अप्रत्याशित और अद्वितीय दोनों के लिए अद्वितीय होना चाहिए एक दी गई कुंजी

आसान की है कि कारण गलतियाँ करने के लिए के लिए, मैं एक कोड का टुकड़ा है, कि मैं की समीक्षा की रखने की कोशिश करें और तारीख तक (टिप्पणी, मुद्दों का स्वागत करते हैं):

Modern Examples of Symmetric Authenticated Encryption of a string C#.

यदि आप इसे AESThenHMAC.AesSimpleDecryptWithPassword(ciphertext, password) का उपयोग जब गलत पासवर्ड का उपयोग किया जाता है, तो null वापस आ जाता है, यदि सिफरटेक्स्ट या iv को एन्क्रिप्शन null संशोधित किया गया है, तो आपको कभी भी जंक डेटा वापस नहीं मिलेगा, या पैडिंग अपवाद नहीं मिलेगा।

16

मुझे एक समान अनुभव हुआ "पैडिंग अमान्य है और इसे हटाया नहीं जा सकता है।" अपवाद, लेकिन मेरे मामले में कुंजी चतुर्थ और पैडिंग सही थे।

यह पता चला कि क्रिप्टो स्ट्रीम को फ्लश करना सब कुछ गायब था।

इस तरह:

  MemoryStream msr3 = new MemoryStream(); 
      CryptoStream encStream = new CryptoStream(msr3, RijndaelAlg.CreateEncryptor(), CryptoStreamMode.Write); 
      encStream.Write(bar2, 0, bar2.Length); 
      // unless we flush the stream we would get "Padding is invalid and cannot be removed." exception when decoding 
      encStream.FlushFinalBlock(); 
      byte[] bar3 = msr3.ToArray(); 
+1

वही करना चाहिए 'encStream.Close(); '। – sharpener

+1

शायद आपको उन वस्तुओं पर 'उपयोग' का उपयोग करना चाहिए क्योंकि वे डिस्पोजेबल हैं। वह पर्याप्त होगा। – user2173353

+1

यह भी ध्यान रखें कि एक सामान्य 'फ्लश()' जिसे आप सामान्य रूप से स्ट्रीम के साथ करेंगे, वह 'CryptoStream' के लिए आवश्यक 'FlushFinalBlock()' जैसा नहीं है। यह कोड से पहले विवरण में थोड़ा अस्पष्ट है। –

0

मैं एक ऐसी ही समस्या थी, डिक्रिप्ट विधि में इस मुद्दे को एक खाली स्मृति धारा आरंभ किया गया था। जब यह काम किया जब मैं इस तरह सिफर पाठ बाइट सरणी के साथ प्रारंभ:

MemoryStream ms = new MemoryStream(cipherText) 
-1

जवाब उपयोगकर्ता "atconway" के द्वारा अद्यतन मेरे लिए काम किया।

समस्या पैडिंग के साथ नहीं थी लेकिन कुंजी जो एन्क्रिप्शन और डिक्रिप्शन के दौरान अलग थी। कुंजी और iv एक ही मूल्य को समझने और डिक्रिप्ट करने के दौरान समान होना चाहिए।

-1

मुझे भी मिल रहा था पैडिंग अमान्य है और संदेश हटाया नहीं जा सकता है। जैसा कि ऊपर बताया गया है, कारण क्रिप्टोस्ट्रीम में कुछ बफर बाइट्स था। - ICryptoTransform के देशी कार्यान्वयन हैं नहीं थ्रेड-सुरक्षित (

using (CryptoStream cryptoStream = new CryptoStream(memoryStream, algorithm.CreateDecryptor(), CryptoStreamMode.Write)) { 
    cryptoStream.Write(bytes, 0, bytes.Length); 
    cryptoStream.FlushFinalBlock(); 
    result = Encoding.UTF8.GetString(memoryStream.ToArray()); 
    return result; 
} 
2

अपवाद की एक और कारण डिक्रिप्शन तर्क का प्रयोग कई धागे के बीच एक रेस स्थिति हो सकता है: यह है कि यह कैसे FlushFinalBlock() विधि को फोन करके तय किया गया था है उदाहरण के लिए सममित एल्गोरिदम), इसलिए इसे विशेष खंड में रखा जाना चाहिए, उदाहरण के लिए लॉक का उपयोग कर। कृपया अधिक जानकारी के लिए यहाँ देखें: http://www.make-awesome.com/2011/07/system-security-cryptography-and-thread-safety/

3

आप FlushFinalBlock() के अलावा मुख्य बेमेल की संभावना से इनकार किया है, तो फिर (यानिव के जवाब देखें), CryptoStream पर Close() बुला भी पर्याप्त होगा।

using (MemoryStream ms = new MemoryStream()) 
using (var enc = RijndaelAlg.CreateEncryptor()) 
{ 
    using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write)) 
    { 
    encStream.Write(bar2, 0, bar2.Length); 
    } // implicit close 
    byte[] encArray = ms.ToArray(); 
} 

मैं इस (या समान) ने काट लिया गया है::

using (MemoryStream ms = new MemoryStream()) 
using (var enc = RijndaelAlg.CreateEncryptor()) 
using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write)) 
{ 
    encStream.Write(bar2, 0, bar2.Length); 
    byte[] encArray = ms.ToArray(); 
} // implicit close -- too late! 

आप using ब्लॉक के साथ सख्ती से संसाधनों को साफ कर रहे हैं, CryptoStream खुद के लिए ब्लॉक घोंसला के लिए सुनिश्चित हो

+1

लेकिन यदि आप 'encStream.FlushFinalBlock()' करते हैं, तो मुझे लगता है कि इससे कोई फर्क नहीं पड़ता कि आप कहां हैं mo.ToArray() '(चाहे क्रिप्टोस्ट्रीम के 'उपयोग' के बाहर या अंदर)। – nawfal

+0

ओपी जानता है कि यह त्रुटि का कारण बनने वाला एक महत्वपूर्ण मेल नहीं है और पूछा कि क्यों एक महत्वपूर्ण मेल नहीं है इस त्रुटि का कारण बनता है। – jbtule

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

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