2011-12-07 24 views
6

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

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

public string[] GenerateKeysToStrings(string uniqueIdentifier) 
    { 
     string[] keys; 
     using (var rsa = new RSACryptoServiceProvider(4096)) 
     { 
      try 
      { 
       string privateKey = rsa.ToXmlString(true); 
       string publicKey = rsa.ToXmlString(false); 

       this.pki.StoreKey(publicKey, uniqueIdentifier); 

       keys = new string[2]; 
       keys[0] = privateKey; 
       keys[1] = publicKey; 
      } 
      finally 
      { 
       //// Clear the RSA key container, deleting generated keys. 
       rsa.PersistKeyInCsp = false; 
      } 
     } 
     return keys; 
    } 

आप देख सकते हैं, मैं कुंजी उत्पन्न और मैं एक PKI mimmick सार्वजनिक कुंजी को उस साधारण वर्ग में भेजकर जो इसे संग्रहीत करता है, और फिर निजी कुंजी को फ़ाइल पर लिखा जाता है (ध्यान दें कि मेरे पास एक और तरीका भी है जो इसे करता है लेकिन इसे इसके बजाय सरणी में संग्रहीत करता है, क्योंकि मैं परीक्षण करना चाहता था और चीजों को सरल बनाएं क्योंकि मुझे No such key exceptions और कभी-कभी क्रिप्टोग्राफ़िक अपवाद मिलते हैं जब मैं इसे पूर्व में दिखाया गया तरीका करता हूं पर्याप्त है, तो मैं बस, rsa.ToXmlString स्ट्रिंग भंडारण एक सरणी में एक स्ट्रिंग है, लेकिन कोई भाग्य के रूप में करके इसे आसान बनाने के लिए करना चाहता था)

अब मैं एक एन्क्रिप्ट है और विधि डिक्रिप्ट इस प्रकार है:।

public string Encrypt(string keyString, string message) 
    { 
     string encryptedMessage; 
     using (var rsa = new RSACryptoServiceProvider()) 
     { 
      try 
      { 
       //// Load the key from the specified path 
       var encryptKey = new XmlDocument(); 
       encryptKey.Load(@"C:\Test\PrivateKeyInfo.xml"); 
       rsa.FromXmlString(encryptKey.OuterXml); 


       //// Conver the string message to a byte array for encryption 
       //// var encoder = new UTF8Encoding(); 
       ASCIIEncoding byteConverter = new ASCIIEncoding(); 
       byte[] dataToEncrypt = byteConverter.GetBytes(message); 

       byte[] encryptedData = rsa.Encrypt(dataToEncrypt, false); 

       //// Convert the byte array back to a string message 
       encryptedMessage = byteConverter.GetString(encryptedData); 
      } 
      finally 
      { 
       //// Clear the RSA key container, deleting generated keys. 
       rsa.PersistKeyInCsp = false; 
      } 
     } 
     return encryptedMessage; 
    } 

डिक्रिप्शन :

public string Decrypt(string keyString, string message) 
    { 
     string decryptedText; 
     using (var rsa = new RSACryptoServiceProvider()) 
     { 
      try 
      { 
       //// Loads the keyinfo into the rsa parameters from the keyfile 
       /* 
       var privateKey = new XmlDocument(); 
       privateKey.Load(keyString); 
       */ 
       rsa.FromXmlString(keyString); 

       //// Convert the text from string to byte array for decryption 
       ASCIIEncoding byteConverter = new ASCIIEncoding(); 
       var encryptedBytes = byteConverter.GetBytes(message); 

       //// Create an aux array to store all the encrypted bytes 
       byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, false); 

       decryptedText = byteConverter.GetString(decryptedBytes); 
      } 
      finally 
      { 
       //// Clear the RSA key container, deleting generated keys. 
       rsa.PersistKeyInCsp = false; 
      } 
     } 
     return decryptedText; 
    } 

मुझे पता है कि इस पाठ की एक दीवार है, लेकिन मुझे आशा है कि आप मुझे बाहर करने में मदद कर सकते हैं, क्योंकि मैं के लिए दीवार के खिलाफ मेरे सिर पीटने किया गया है इतने लंबे समय के लिए अब यह हास्यास्पद नहीं है :)

समस्या है, मैं कैसे साथ एन्क्रिप्ट करने संदेशों के बारे में जाते हो RSA (या किसी अन्य सार्वजनिक/निजी कुंजी एन्क्रिप्शन)

यहाँ टेस्ट ग्राहक है:

public static void Main(string[] args) 
    { 
     PublicKeyInfrastructure pki = new PublicKeyInfrastructure(); 
     Cryptograph crypto = new Cryptograph(); 
     string[] keys = crypto.GenerateKeysToStrings("[email protected]"); 


     string plainText = "Hello play with me, please"; 
     string publicKey = crypto.GetPublicKey("[email protected]"); 

     string encryptedText = crypto.Encrypt(keys[0], plainText); 


     string decryptedText = crypto.Decrypt(keys[1], encryptedText); 

    } 

जैसा कि मैंने उल्लेख किया है, स्ट्रिंग सरणियों हैं वहाँ क्योंकि मैं एक्सएमएल दस्तावेज़ों से खराब पार्सिंग त्रुटि को खत्म करना चाहता था ...

जब मैं परीक्षण क्लाइंट चलाता हूं, अगर मैं एन्क्रिप्ट करने के लिए निजी कुंजी का उपयोग करता हूं और डिक्रिप्ट करने के लिए सार्वजनिक कुंजी का उपयोग करता हूं, तो मुझे "कुंजी मौजूद नहीं है" अगर मैं इसे दूसरी तरफ करता हूं, तो मुझे एक खराब डेटा अपवाद मिलता है।

कृपया मुझे लोगों की मदद करें, अगर आपको कोई अच्छी मार्गदर्शिका पता है, या मुझे बता सकता है कि स्ट्रिंग संदेशों पर सार्वजनिक/निजी कुंजी एन्क्रिप्शन को कुछ हद तक सीधे कैसे लागू किया जाए, तो कृपया मेरी मदद करें।

मैं किसी भी मदद की सराहना करता हूं।

उत्तर

5

यह नहीं है कि आरएसए एन्क्रिप्शन कैसे किया जाना चाहिए।

आरएसए गणित के बारे में सब कुछ है। जो आपने एन्क्रिप्ट किया है वह एक संख्या है इसलिए इसे सीमित लंबाई और आरएसए कीपैयर लंबाई से मेल खाना चाहिए जो आप उपयोग कर रहे हैं। उपयोग की जाने वाली पैडिंग द्वारा आगे की लंबाई सीमाएं लगाई जाती हैं (या तो पीकेसीएस # 1 या ओएईपी)।

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

तुम मेरे blog पर इस लागू करने के बारे पढ़ सकते हैं।

+0

मैं अपने प्रोफेसर के साथ और उस समय देखने की मेरी बात यह थी कि यह एक कुंजी एन्क्रिप्ट करने, चाबी का आदान-प्रदान बेहतर होगा और कम से बात की जांच करने के लिए की तरह होगा फिर इसे एक सममित एल्गोरिदम के आधार के रूप में उपयोग करें, जैसे कि संदेश को एन्क्रिप्ट/डिक्रिप्ट करने के लिए रिजेंडेल की तरह, हालांकि, वह नहीं चाहते थे कि हम सममित एन्क्रिप्शन का उपयोग करें, इसलिए अब मैं ऐसी स्थिति में हूं जहां यह अब के लिए ऑफ-सीमा है। निष्पादन के अनुसार, जब उपयोगकर्ता नाम और पासवर्ड वाले HTTP संदेशों के बारे में बात करते हैं, तो संदेशों को एन्क्रिप्ट करने में 501 बाइट्स (4096 बिट आरएसए कुंजी का उपयोग करके) कितना समय लगेगा? अवरुद्ध ब्लॉक ब्लॉक या नहीं, मुझे अभी भी आरएसए का उपयोग करने में समस्याएं हैं :( –

+0

आप आकार सीमा (पैडिंग शामिल) के तहत रहने के लिए आरएसए एन्क्रिप्शन/डिक्रिप्शन को लूप कर सकते हैं और परिणामों को जोड़/विभाजित कर सकते हैं। कितना समय? आपका सीपीयू, क्या यह एक पुराना स्मार्टफोन और एक नया 8 कोर सर्वर है? ;-) लेकिन सही विकल्प से काफी लंबा है। – poupou

+0

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

0

शायद मुझे कुछ याद आ रहा है, लेकिन ऐसा लगता है कि आपका एन्क्रिप्टेड() फ़ंक्शन keyString पैरामीटर या encryptKey की सामग्री का उपयोग नहीं करता है।

+0

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

1

ठीक है, मैं अंत में समस्या मैं अपने मूल पोस्ट में कहा गया है के लिए एक समाधान के साथ आए हैं। यह ऐसा कुछ है जिसे मैंने पूरी तरह से परीक्षण नहीं किया है या कुछ भी नहीं, लेकिन कुछ मैंने परीक्षण और त्रुटि प्रक्रिया से कुछ पता लगाया है।

यहाँ वर्तमान कोड रहा है:

public static string Encrypt(string dataToEncrypt, RSAParameters publicKeyInfo) 
    { 
     //// Our bytearray to hold all of our data after the encryption 
     byte[] encryptedBytes = new byte[0]; 
     using (var RSA = new RSACryptoServiceProvider()) 
     { 
      try 
      { 
       //Create a new instance of RSACryptoServiceProvider. 
       UTF8Encoding encoder = new UTF8Encoding(); 

       byte[] encryptThis = encoder.GetBytes(dataToEncrypt); 

       //// Importing the public key 
       RSA.ImportParameters(publicKeyInfo); 

       int blockSize = (RSA.KeySize/8) - 32; 

       //// buffer to write byte sequence of the given block_size 
       byte[] buffer = new byte[blockSize]; 

       byte[] encryptedBuffer = new byte[blockSize]; 

       //// Initializing our encryptedBytes array to a suitable size, depending on the size of data to be encrypted 
       encryptedBytes = new byte[encryptThis.Length + blockSize - (encryptThis.Length % blockSize) + 32]; 

       for (int i = 0; i < encryptThis.Length; i += blockSize) 
       { 
        //// If there is extra info to be parsed, but not enough to fill out a complete bytearray, fit array for last bit of data 
        if (2 * i > encryptThis.Length && ((encryptThis.Length - i) % blockSize != 0)) 
        { 
         buffer = new byte[encryptThis.Length - i]; 
         blockSize = encryptThis.Length - i; 
        } 

        //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it 
        if (encryptThis.Length < blockSize) 
        { 
         buffer = new byte[encryptThis.Length]; 
         blockSize = encryptThis.Length; 
        } 

        //// encrypt the specified size of data, then add to final array. 
        Buffer.BlockCopy(encryptThis, i, buffer, 0, blockSize); 
        encryptedBuffer = RSA.Encrypt(buffer, false); 
        encryptedBuffer.CopyTo(encryptedBytes, i); 
       } 
      } 
      catch (CryptographicException e) 
      { 
       Console.Write(e); 
      } 
      finally 
      { 
       //// Clear the RSA key container, deleting generated keys. 
       RSA.PersistKeyInCsp = false; 
      } 
     } 
     //// Convert the byteArray using Base64 and returns as an encrypted string 
     return Convert.ToBase64String(encryptedBytes); 
    } 

    /// <summary> 
    /// Decrypt this message using this key 
    /// </summary> 
    /// <param name="dataToDecrypt"> 
    /// The data To decrypt. 
    /// </param> 
    /// <param name="privateKeyInfo"> 
    /// The private Key Info. 
    /// </param> 
    /// <returns> 
    /// The decrypted data. 
    /// </returns> 
    public static string Decrypt(string dataToDecrypt, RSAParameters privateKeyInfo) 
    { 
     //// The bytearray to hold all of our data after decryption 
     byte[] decryptedBytes; 

     //Create a new instance of RSACryptoServiceProvider. 
     using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) 
     { 
      try 
      { 
       byte[] bytesToDecrypt = Convert.FromBase64String(dataToDecrypt); 

       //// Import the private key info 
       RSA.ImportParameters(privateKeyInfo); 

       //// No need to subtract padding size when decrypting (OR do I?) 
       int blockSize = RSA.KeySize/8; 

       //// buffer to write byte sequence of the given block_size 
       byte[] buffer = new byte[blockSize]; 

       //// buffer containing decrypted information 
       byte[] decryptedBuffer = new byte[blockSize]; 

       //// Initializes our array to make sure it can hold at least the amount needed to decrypt. 
       decryptedBytes = new byte[dataToDecrypt.Length]; 

       for (int i = 0; i < bytesToDecrypt.Length; i += blockSize) 
       { 
        if (2 * i > bytesToDecrypt.Length && ((bytesToDecrypt.Length - i) % blockSize != 0)) 
        { 
         buffer = new byte[bytesToDecrypt.Length - i]; 
         blockSize = bytesToDecrypt.Length - i; 
        } 

        //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it 
        if (bytesToDecrypt.Length < blockSize) 
        { 
         buffer = new byte[bytesToDecrypt.Length]; 
         blockSize = bytesToDecrypt.Length; 
        } 

        Buffer.BlockCopy(bytesToDecrypt, i, buffer, 0, blockSize); 
        decryptedBuffer = RSA.Decrypt(buffer, false); 
        decryptedBuffer.CopyTo(decryptedBytes, i); 
       } 
      } 
      finally 
      { 
       //// Clear the RSA key container, deleting generated keys. 
       RSA.PersistKeyInCsp = false; 
      } 
     } 

     //// We encode each byte with UTF8 and then write to a string while trimming off the extra empty data created by the overhead. 
     var encoder = new UTF8Encoding(); 
     return encoder.GetString(decryptedBytes).TrimEnd(new[] { '\0' }); 

    } 

जैसा कि मैंने कहा, मैं इसे बहुत का परीक्षण किया है नहीं, नीचे दिए गए आकारों, पर और ब्लॉक आकार से ऊपर के अलावा अन्य है, लेकिन यह क्या कर किया जा रहा है यह होना चाहिए। मैं अभी भी एक नौसिखिया हूँ, इसलिए मैं वास्तव में आप मेरी कोड :)