2012-02-11 22 views
15

मुझे एन्क्रिप्ट करना, स्टोर करना और बाद में बड़ी फ़ाइलों को डिक्रिप्ट करना है। ऐसा करने का सबसे अच्छा तरीका क्या है? मैंने सुना है कि आरएसए एन्क्रिप्शन महंगा है और एईएस कुंजी एन्क्रिप्ट करने के लिए आरएसए का उपयोग करने की सलाह दी गई थी और फिर बड़ी फ़ाइलों को एन्क्रिप्ट करने के लिए एईएस कुंजी का उपयोग किया गया था। उदाहरण के साथ कोई सुझाव महान होगा।बड़ी फ़ाइलों को एन्क्रिप्ट/डिक्रिप्ट करना (.NET)

+0

यहाँ एक उदाहरण है [ब्लॉग पोस्टिंग] (http://www.technical-recipes.com/2013/using-rsa-to- एन्क्रिप्ट-बड़े-डेटा-फाइल-इन-सी /), डाउनलोड करने योग्य [विजुअल स्टूडियो 2010 प्रोजेक्ट] (http://www.technical-recipes.com/Downloads/crypt.7z) जो बस यही करता है। – AndyUK

उत्तर

10

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

+1

धन्यवाद, लेकिन मेरी समस्या थोड़ा अलग है। मैं बड़ी फाइलों को एन्क्रिप्ट करना चाहता हूं और फिर स्टोर में समझौता होने पर एन्क्रिप्शन (यानी सुरक्षा) की आवश्यकता होती है। क्लाइंट सर्वर संचार के लिए मैं आरएसए के साथ एन्क्रिप्ट की गई एईएस कुंजी में भेजता हूं, यह मेरे परिदृश्य में कैसे बदलता है? क्या मैं एईएस कुंजी को पूर्व-लंबित या सममित कुंजी एन्क्रिप्टेड ब्लॉब के बाइट जोड़ने के हिस्से के रूप में संग्रहीत करता हूं? – kalrashi

+0

वास्तव में X509Certificate2 एमएसडीएन दस्तावेज़ (मैं RSACryptoProvider और संबंधित कक्षाओं में देख रहा था) पर एक महान उदाहरण पाया जाता है: – kalrashi

8

एक जीव का बड़ा एक और खूबसूरत है, हालांकि हम इसे देखते समय महंगे जानते हैं। आँख झपकना।

संपादित करें 2012/02/13:

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

using System; 
using System.IO; 
using System.Security.Cryptography; 
using System.Text; 

... 

    // Rfc2898DeriveBytes constants: 
    public readonly byte[] salt = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Must be at least eight bytes. MAKE THIS SALTIER! 
    public const int iterations = 1042; // Recommendation is >= 1000. 

    /// <summary>Decrypt a file.</summary> 
    /// <remarks>NB: "Padding is invalid and cannot be removed." is the Universal CryptoServices error. Make sure the password, salt and iterations are correct before getting nervous.</remarks> 
    /// <param name="sourceFilename">The full path and name of the file to be decrypted.</param> 
    /// <param name="destinationFilename">The full path and name of the file to be output.</param> 
    /// <param name="password">The password for the decryption.</param> 
    /// <param name="salt">The salt to be applied to the password.</param> 
    /// <param name="iterations">The number of iterations Rfc2898DeriveBytes should use before generating the key and initialization vector for the decryption.</param> 
    public void DecryptFile(string sourceFilename, string destinationFilename, string password, byte[] salt, int iterations) 
    { 
     AesManaged aes = new AesManaged(); 
     aes.BlockSize = aes.LegalBlockSizes[0].MaxSize; 
     aes.KeySize = aes.LegalKeySizes[0].MaxSize; 
     // NB: Rfc2898DeriveBytes initialization and subsequent calls to GetBytes must be eactly the same, including order, on both the encryption and decryption sides. 
     Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt, iterations); 
     aes.Key = key.GetBytes(aes.KeySize/8); 
     aes.IV = key.GetBytes(aes.BlockSize/8); 
     aes.Mode = CipherMode.CBC; 
     ICryptoTransform transform = aes.CreateDecryptor(aes.Key, aes.IV); 

     using (FileStream destination = new FileStream(destinationFilename, FileMode.CreateNew, FileAccess.Write, FileShare.None)) 
     { 
      using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write)) 
      { 
       try 
       { 
        using (FileStream source = new FileStream(sourceFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) 
        { 
         source.CopyTo(cryptoStream); 
        } 
       } 
       catch (CryptographicException exception) 
       { 
        if (exception.Message == "Padding is invalid and cannot be removed.") 
         throw new ApplicationException("Universal Microsoft Cryptographic Exception (Not to be believed!)", exception); 
        else 
         throw; 
       } 
      } 
     } 
    } 

    /// <summary>Encrypt a file.</summary> 
    /// <param name="sourceFilename">The full path and name of the file to be encrypted.</param> 
    /// <param name="destinationFilename">The full path and name of the file to be output.</param> 
    /// <param name="password">The password for the encryption.</param> 
    /// <param name="salt">The salt to be applied to the password.</param> 
    /// <param name="iterations">The number of iterations Rfc2898DeriveBytes should use before generating the key and initialization vector for the decryption.</param> 
    public void EncryptFile(string sourceFilename, string destinationFilename, string password, byte[] salt, int iterations) 
    { 
     AesManaged aes = new AesManaged(); 
     aes.BlockSize = aes.LegalBlockSizes[0].MaxSize; 
     aes.KeySize = aes.LegalKeySizes[0].MaxSize; 
     // NB: Rfc2898DeriveBytes initialization and subsequent calls to GetBytes must be eactly the same, including order, on both the encryption and decryption sides. 
     Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt, iterations); 
     aes.Key = key.GetBytes(aes.KeySize/8); 
     aes.IV = key.GetBytes(aes.BlockSize/8); 
     aes.Mode = CipherMode.CBC; 
     ICryptoTransform transform = aes.CreateEncryptor(aes.Key, aes.IV); 

     using (FileStream destination = new FileStream(destinationFilename, FileMode.CreateNew, FileAccess.Write, FileShare.None)) 
     { 
      using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write)) 
      { 
       using (FileStream source = new FileStream(sourceFilename, FileMode.Open, FileAccess.Read, FileShare.Read)) 
       { 
        source.CopyTo(cryptoStream); 
       } 
      } 
     } 
    } 
+0

यह उदाहरण केवल एईएस का उपयोग करके एन्क्रिप्ट/डिक्रिप्ट करता है।क्या आप कहने का मतलब है कि आरएसए और प्रोफाइल दोनों के साथ समान चीज का प्रयास करें? – kalrashi

+0

यह आप पर निर्भर है। आपके प्रश्न ने आंकड़ों के खिलाफ अनुमानित खतरों (फाइलों का आकार, किसी भी नेटवर्क स्थानान्तरण या जोखिम में शामिल, संसाधन प्रसंस्करण संसाधनों, के बारे में समझाया नहीं है ...। इस मामले में ऐसा लगता है कि आप अपने पर्यावरण में एन्क्रिप्शन की लागत पर कम से कम एक छोटे बेंचमार्क डेटा एकत्र करने और वहां से काम करने के लिए अच्छा प्रदर्शन करेंगे। अन्य ने सार्वजनिक बनाम निजी कुंजी क्रिप्टोग्राफी और विभिन्न एल्गोरिदम की सापेक्ष ताकत पर स्पर्श किया है। – HABO

+2

"पैडिंग अमान्य है और इसे हटाया नहीं जा सकता है" से बचने के लिए। अपवाद, एन्क्रिप्टिंग पक्ष को स्रोत के बाद 'स्रोत.फ्लैशफिनलब्लॉक()' को कॉल करना होगा। कॉपी (क्रोटोस्ट्रीम); अन्यथा आप वास्तव में अंतिम ब्लॉक को गलत मानेंगे। – DipSwitch

3

जैसा आप असममित क्रिप्टोग्राफी में सुना है, आरएसए की तरह, सममित क्रिप्टोग्राफी (जैसे एईएस) की तुलना में बहुत धीमी है, लेकिन यह यह फायदे (सरल कुंजी प्रबंधन, उदा की रक्षा के लिए एक भी निजी कुंजी) है करता है।

कुंजी (पन इरादा) कुंजी (असममित और गतिशीलता की गति की निजी कुंजी) के फायदे का उपयोग करना है जबकि दूसरी (कई गुप्त कुंजी और धीमी गति) की असुविधा को अनदेखा करते हुए।

आप अपनी बड़ी फ़ाइल को एन्क्रिप्ट करने के लिए उपयोग की जाने वाली एक (सममित) गुप्त कुंजी को एन्क्रिप्ट करने के लिए प्रति फ़ाइल (कोई बड़ा प्रदर्शन प्रभाव) आरएसए का उपयोग करके ऐसा कर सकते हैं। सममित कुंजी के रैपिंग आपको केवल एक एकल, निजी कुंजी का प्रबंधन करने की अनुमति देता है।

यहां मेरे पुराने (लेकिन अभी भी सत्य) blog post का एक लिंक है जो सी # और .NET फ्रेमवर्क (मोनो के माइक्रोसॉफ्ट) का उपयोग करके ऐसा करने का एक उदाहरण देता है।

+0

धन्यवाद। उदाहरण काफी उपयोगी था। – kalrashi

10

यह मदद मिल सकती है

/// Encrypts a file using Rijndael algorithm. 
///</summary> 
///<param name="inputFile"></param> 
///<param name="outputFile"></param> 
private void EncryptFile(string inputFile, string outputFile) 
{ 

    try 
    { 
     string password = @"myKey123"; // Your Key Here 
     UnicodeEncoding UE = new UnicodeEncoding(); 
     byte[] key = UE.GetBytes(password); 

     string cryptFile = outputFile; 
     FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create); 

     RijndaelManaged RMCrypto = new RijndaelManaged(); 

     CryptoStream cs = new CryptoStream(fsCrypt, 
      RMCrypto.CreateEncryptor(key, key), 
      CryptoStreamMode.Write); 

     FileStream fsIn = new FileStream(inputFile, FileMode.Open); 

     int data; 
     while ((data = fsIn.ReadByte()) != -1) 
      cs.WriteByte((byte)data); 


     fsIn.Close(); 
     cs.Close(); 
     fsCrypt.Close(); 
    } 
    catch 
    { 
     MessageBox.Show("Encryption failed!", "Error"); 
    } 
} 

/// 
/// Decrypts a file using Rijndael algorithm. 
///</summary> 
///<param name="inputFile"></param> 
///<param name="outputFile"></param> 
private void DecryptFile(string inputFile, string outputFile) 
{ 

    { 
     string password = @"myKey123"; // Your Key Here 

     UnicodeEncoding UE = new UnicodeEncoding(); 
     byte[] key = UE.GetBytes(password); 

     FileStream fsCrypt = new FileStream(inputFile, FileMode.Open); 

     RijndaelManaged RMCrypto = new RijndaelManaged(); 

     CryptoStream cs = new CryptoStream(fsCrypt, 
      RMCrypto.CreateDecryptor(key, key), 
      CryptoStreamMode.Read); 

     FileStream fsOut = new FileStream(outputFile, FileMode.Create); 

     int data; 
     while ((data = cs.ReadByte()) != -1) 
      fsOut.WriteByte((byte)data); 

     fsOut.Close(); 
     cs.Close(); 
     fsCrypt.Close(); 

    } 
} 

स्रोत: http://www.codeproject.com/Articles/26085/File-Encryption-and-Decryption-in-C

+2

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

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