2013-11-01 6 views
18

मैं MemoryStream बना रहा हूं, इसे CryptoStream पर लिखने के लिए पास करें। मैं CryptoStream एन्क्रिप्ट करने के लिए चाहता हूं, और MemoryStream मेरे लिए खोलने के लिए कुछ और पढ़ने के लिए छोड़ दें। लेकिन जैसे ही CryptoStream का निपटारा किया जाता है, यह MemoryStream का भी निपटान करता है।क्या क्रिप्टोस्ट्रीम आधार स्ट्रीम को छोड़ सकता है?

CryptoStream आधार MemoryStream किसी भी तरह से खोल सकते हैं?

using (MemoryStream scratch = new MemoryStream()) 
{ 
    using (AesManaged aes = new AesManaged()) 
    { 
     // <snip> 
     // Set some aes parameters, including Key, IV, etc. 
     // </snip> 
     ICryptoTransform encryptor = aes.CreateEncryptor(); 
     using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write)) 
     { 
      myCryptoStream.Write(someByteArray, 0, someByteArray.Length); 
     } 
    } 
    // Here, I'm still within the MemoryStream block, so I expect 
    // MemoryStream to still be usable. 
    scratch.Position = 0; // Throws ObjectDisposedException 
    byte[] scratchBytes = new byte[scratch.Length]; 
    scratch.Read(scratchBytes,0,scratchBytes.Length); 
    return Convert.ToBase64String(scratchBytes); 
} 
+0

आप पहली जगह स्ट्रीम का उपयोग क्यों कर रहे हैं? इनपुट बाइट्स पर बस 'एन्क्रिप्टर। ट्रांसफॉर्मफिनलब्लॉक' पर कॉल करें। स्ट्रीम अधिकतर वृद्धिशील एन्क्रिप्शन/डिक्रिप्शन के लिए उपयोगी होते हैं, लेकिन जब आपके पास एक ही समय में पूर्ण डेटा उपलब्ध नहीं होता है। – CodesInChaos

उत्तर

9

आप कर सकते हैं लेकिन आप कथन का उपयोग करने में सक्षम नहीं होंगे। आपको ऑब्जेक्ट का निपटान मैन्युअल रूप से प्रबंधित करने की आवश्यकता होगी और आपको यह सुनिश्चित करने के लिए FlushFinialBlock() पर कॉल करने की आवश्यकता होगी ताकि सभी डेटा अंतर्निहित स्ट्रीम पर काम करने से पहले लिखा जा सके।

एक बार जब आप स्ट्रीम के साथ काम कर रहे हैं तो आप अंत में अंत में अवरुद्ध होने वाले सभी संसाधनों का निपटान कर सकते हैं।

MemoryStream scratch = null; 
AesManaged aes = null; 
CryptoStream myCryptoStream = null; 
try 
{ 
    scratch = new MemoryStream(); 
    aes = new AesManaged(); 

    // <snip> 
    // Set some aes parameters, including Key, IV, etc. 
    // </snip> 
    ICryptoTransform encryptor = aes.CreateEncryptor(); 
    myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write); 
    myCryptoStream.Write(someByteArray, 0, someByteArray.Length); 

    //Flush the data out so it is fully written to the underlying stream. 
    myCryptoStream.FlushFinalBlock(); 

    scratch.Position = 0; 
    byte[] scratchBytes = new byte[scratch.Length]; 
    scratch.Read(scratchBytes,0,scratchBytes.Length); 
    return Convert.ToBase64String(scratchBytes); 
} 
finally 
{ 
    //Dispose all of the disposeable objects we created in reverse order. 

    if(myCryptoStream != null) 
     myCryptoStream.Dispose(); 

    if(aes != null) 
     aes.Dispose(); 

    if(scratch != null) 
     scratch.Dispose(); 
} 
+1

जिस व्यक्ति ने मुझे एक -1 दिया था, उसके जवाब के बारे में आपने एक -1 वारंट करने के लिए "उपयोगी नहीं" माना था? अगर मेरी पोस्ट में गलत जानकारी है तो कृपया मुझे सूचित करें ताकि मैं इसे सही या हटा सकूं। मुझे लगता है कि जिस तरह से कोड लिखा गया है, आंतरिक 'कोशिश-अंत' अनावश्यक है। मैं इसे हटा दूंगा। एकमात्र अन्य चीज जिसे मैं सोच सकता हूं वह यह तथ्य है कि 'mysryptoStream' से पहले 'एईएस' और 'स्क्रैच' का निपटारा किया जाता है। मैं भी इसे सही कर दूंगा। –

+1

क्या होगा यदि आप एक ऐसी विधि लिखना चाहते हैं जो बेस स्ट्रीम को एन्क्रिप्ट करने के बाद मूल स्ट्रीम लौटाती है और बेस स्ट्रीम लौटने से पहले क्रिप्टोस्ट्रीम का निपटान करती है? क्या आप क्रिप्टोस्ट्रीम का निपटान करते हैं तो इससे कोई फर्क पड़ता है? या जब आप इसके साथ काम करते हैं तो बस बेसस्ट्रीम का निपटान करना ठीक है? –

+0

डाउनवॉटेड: क्रिप्टोस्ट्रीम का उपयोग – Hammerite

6

यह पता चला, वहाँ का उपयोग कर अलग तोड़ने के लिए {} कोशिश में ब्लॉक {} {} अंत में किसी भी आवश्यकता नहीं है ... अंत में, तुम सिर्फ कथन का उपयोग अंदर FlushFinalBlock() का उपयोग करने के लिए है, और आवश्यकतानुसार अंदर और कुछ भी घोंसला।

using (MemoryStream scratch = new MemoryStream()) 
{ 
    using (AesManaged aes = new AesManaged()) 
    { 
     // <snip> 
     // Set some aes parameters, including Key, IV, etc. 
     // </snip> 
     ICryptoTransform encryptor = aes.CreateEncryptor(); 
     using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write)) 
     { 
      myCryptoStream.Write(someByteArray, 0, someByteArray.Length); 
      myCryptoStream.FlushFinalBlock(); 
      scratch.Flush(); // not sure if this is necessary 
      byte[] scratchBytes = scratch.ToArray(); 
      return Convert.ToBase64String(scratchBytes); 
     } 
    } 
} 
+2

'स्क्रैच.फ्लश()' वास्तव में अनैच्छिक है, [msdn से] (http://msdn.microsoft.com/) से मूल स्ट्रीम को वापस करने के तरीके को संबोधित नहीं करता है। en-us/library/system.io.memorystream.flush.aspx) "* स्ट्रीम को ओवरराइड करता है। फ्लश विधि ताकि कोई कार्रवाई नहीं की जा सके। *" –

11

एक दूसरे समाधान के रूप में, आप एक WrapperStream उद्देश्य यह है कि बस निपटान/बंद के अलावा के साथ हर कॉल गुजरता बना सकते हैं। अपनी मेमोरी स्ट्रीम के चारों ओर एक रैपर बनाएं, रैपर को क्रिप्टो स्ट्रीम पर रखें, और अब क्रिप्टो स्ट्रीम को बंद करना मेमोरी स्ट्रीम को स्पर्श नहीं करता है।

5

मेरे सरल उपाय:

class NotClosingCryptoStream : CryptoStream 
{ 
    public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode) 
     : base(stream, transform, mode) 
    { 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if(!HasFlushedFinalBlock) 
      FlushFinalBlock(); 

     base.Dispose(false); 
    } 
}
+0

यह काम करता है, लेकिन मेरे पास एक सवाल है: क्योंकि एमएसडीएन का उल्लेख करता है ' का निपटान टाइप करें: सिस्टम।बूलियन दोनों प्रबंधित और अप्रबंधित संसाधनों को जारी करने के लिए सच है; केवल अप्रबंधित संसाधनों को रिलीज करने के लिए झूठा '। लेकिन जैसा कि मुझे पता है, स्ट्रीम ऑब्जेक्ट अप्रबंधित ऑब्जेक्ट्स है, तो यह समाधान क्रिप्टोस्ट्रीम को अंतर्निहित धारा को क्यों जारी नहीं कर सकता है? – Gintama

0

रूप @CyberBasti जवाब दे दिया। मुझे लगता है कि सबसे अच्छा समाधान निपटान विधि को ओवरराइड करना है और false के साथ आधार का आह्वान करना है।

मैं reference source में देखा और यह सबसे अच्छा समाधान हो सकता है क्योंकि आप अभी भी using कीवर्ड का उपयोग करें और क्योंकि मैं टिप्पणी नहीं कर सकता मैं एक जवाब बना रही हूँ संगठित कोड :)

btw कर सकते हैं पता चलता xD

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