2009-08-20 16 views
57

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

मैं RSACryptoServiceProvider क्लास का उपयोग करना चाहता हूं।

मेरी चाबियाँ बनाने के लिए मेरा कोड यहां है।

public static void AssignNewKey(){ 
    const int PROVIDER_RSA_FULL = 1; 
    const string CONTAINER_NAME = "KeyContainer"; 
    CspParameters cspParams; 
    cspParams = new CspParameters(PROVIDER_RSA_FULL); 
    cspParams.KeyContainerName = CONTAINER_NAME; 
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore; 
    cspParams.ProviderName = "Microsoft Strong Cryptographic Provider"; 
    rsa = new RSACryptoServiceProvider(cspParams); 

    string publicPrivateKeyXML = rsa.ToXmlString(true); 
    string publicOnlyKeyXML = rsa.ToXmlString(false); 
    // do stuff with keys... 
} 

अब योजना निजी कुंजी एक्सएमएल को प्रबंधकों की कुंजी श्रृंखला से जुड़े यूएसबी ड्राइव पर स्टोर करना है।

जब भी कोई प्रबंधक कंपनी छोड़ देता है, तो मैं नई सार्वजनिक और निजी कुंजी उत्पन्न करने में सक्षम होना चाहता हूं (और सभी सार्वजनिक रूप से संग्रहीत सीसी संख्याओं को नई सार्वजनिक कुंजी के साथ फिर से एन्क्रिप्ट करें)।

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

अद्यतन। मेरा टेस्ट कोड नीचे है .:
नोट: यहां "निजीकी" पैरामीटर मूल निजी कुंजी है। कुंजी बदलने के लिए मुझे यह सत्यापित करने की आवश्यकता है कि निजी कुंजी मान्य है।

Default.aspx.cs

public void DownloadNewPrivateKey_Click(object sender, EventArgs e) 
{ 
    StreamReader reader = new StreamReader(fileUpload.FileContent); 
    string privateKey = reader.ReadToEnd(); 
    Response.Clear(); 
    Response.ContentType = "text/xml"; 
    Response.End(); 
    Response.Write(ChangeKeysAndReturnNewPrivateKey(privateKey)); 
} 

में Crytpography.cs में:

public static privateKey; 
public static publicKey; 
public static RSACryptoServiceProvider rsa; 

public static string ChangeKeysAndReturnNewPrivateKey(string _privatekey) 
{ 

    string testData = "TestData"; 
    string testSalt = "salt"; 
    // encrypt the test data using the exisiting public key... 
    string encryptedTestData = EncryptData(testData, testSalt); 
    try 
    { 
     // try to decrypt the test data using the _privatekey provided by user... 
     string decryptTestData = DecryptData(encryptedTestData, _privatekey, testSalt); 
     // if the data is successfully decrypted assign new keys... 
     if (decryptTestData == testData) 
     { 
      AssignNewKey(); 
      // "AssignNewKey()" should set "privateKey" to the newly created private key... 
      return privateKey; 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 
    catch (Exception ex) 
    { 
     return string.Empty; 
    } 
} 
public static void AssignParameter(){ 
    const int PROVIDER_RSA_FULL = 1; 
    const string CONTAINER_NAME = "KeyContainer"; 
    CspParameters cspParams; 
    cspParams = new CspParameters(PROVIDER_RSA_FULL); 
    cspParams.KeyContainerName = CONTAINER_NAME; 
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore; 
    cspParams.ProviderName = "Microsoft Strong Cryptographic Provider"; 
    rsa = new RSACryptoServiceProvider(cspParams); 
} 
public static void AssignNewKey() 
{ 
    AssignParameter(); 

    using (SqlConnection myConn = new SqlConnection(Utilities.ConnectionString)) 
    { 
     SqlCommand myCmd = myConn.CreateCommand(); 

     string publicPrivateKeyXML = rsa.ToXmlString(true); 
     privateKey = publicPrivateKeyXML; // sets the public variable privateKey to the new private key. 

     string publicOnlyKeyXML = rsa.ToXmlString(false); 
     publicKey = publicOnlyKeyXML; // sets the public variable publicKey to the new public key. 

     myCmd.CommandText = "UPDATE Settings SET PublicKey = @PublicKey"; 
     myCmd.Parameters.AddWithValue("@PublicKey", publicOnlyKeyXML); 
     myConn.Open(); 

     myComm.ExecuteScalar(); 
    } 
} 
public static string EncryptData(string data2Encrypt, string salt) 
{ 
    AssignParameter(); 

    using (SqlConnection myConn = new SqlConnection(Utilities.ConnectionString)) 
    { 
     SqlCommand myCmd = myConn.CreateCommand(); 

     myCmd.CommandText = "SELECT TOP 1 PublicKey FROM Settings"; 

     myConn.Open(); 

     using (SqlDataReader sdr = myCmd.ExecuteReader()) 
     { 
      if (sdr.HasRows) 
      { 
       DataTable dt = new DataTable(); 
       dt.Load(sdr); 
       rsa.FromXmlString(dt.Rows[0]["PublicKey"].ToString()); 
      } 
     } 
    } 

    //read plaintext, encrypt it to ciphertext 
    byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data2Encrypt + salt); 
    byte[] cipherbytes = rsa.Encrypt(plainbytes, false); 
    return Convert.ToBase64String(cipherbytes); 
} 
public static string DecryptData(string data2Decrypt, string privatekey, string salt) 
{ 
    AssignParameter(); 

    byte[] getpassword = Convert.FromBase64String(data2Decrypt); 

    string publicPrivateKeyXML = privatekey; 
    rsa.FromXmlString(publicPrivateKeyXML); 

    //read ciphertext, decrypt it to plaintext 
    byte[] plain = rsa.Decrypt(getpassword, false); 
    string dataAndSalt = System.Text.Encoding.UTF8.GetString(plain); 
    return dataAndSalt.Substring(0, dataAndSalt.Length - salt.Length); 
} 
+0

आप इसका परीक्षण कैसे कर रहे हैं? –

+0

मैं मूल रूप से एक .NET पृष्ठ से AssignNewKey() फ़ंक्शन को कॉल कर रहा हूं और फिर अपने पिछले संस्करण के विरुद्ध नया "publicPrivateKeyXML" देख रहा हूं। मैं अपना टेस्ट कोड शामिल करने के लिए ऊपर दिए गए प्रश्न को अपडेट करूंगा। –

+2

यह थोड़ा टेंगेंशियल है, लेकिन क्या आपको एहसास है कि क्रेडिट कार्ड नंबरों को स्टोर करने के लिए आपको अपने सिस्टम को पीसीआई अनुपालन की आवश्यकता है? Http://stackoverflow.com/questions/4300863/storing-credit-card-number-pci – Art

उत्तर

7

क्या मैं कर रहा समाप्त हो गया एक नया KeyContainer बनाने है जब भी मुझे एक नई कुंजी बनाने की आवश्यकता होती है तो वर्तमान दिनांकटाइम (DateTime.Now.Ticks.ToString()) के आधार पर नाम डेटाबेस में कंटेनर नाम और सार्वजनिक कुंजी को सहेजें। साथ ही, जब भी मैं एक नई कुंजी बनाता हूं, तो मैं निम्नलिखित कार्य करता हूं:

public static string ConvertToNewKey(string oldPrivateKey) 
{ 

    // get the current container name from the database... 

    rsa.PersistKeyInCsp = false; 
    rsa.Clear(); 
    rsa = null; 

    string privateKey = AssignNewKey(true); // create the new public key and container name and write them to the database... 

     // re-encrypt existing data to use the new keys and write to database... 

    return privateKey; 
} 
public static string AssignNewKey(bool ReturnPrivateKey){ 
    string containerName = DateTime.Now.Ticks.ToString(); 
    // create the new key... 
    // saves container name and public key to database... 
    // and returns Private Key XML. 
} 

नई कुंजी बनाने से पहले।

+1

यदि आप पूर्ण समाधान पोस्ट करते हैं तो यह अच्छा होगा क्योंकि मैं यह नहीं समझ सकता कि टिप्पणियों में क्या किया जा रहा है – ShaneKm

+0

क्या मैं आपका कोड सही ढंग से पढ़ रहा हूं? आपके पास 'PrivateKey' नामक एक चर है लेकिन आपकी टिप्पणियां आपको एक नई सार्वजनिक कुंजी बनाने का सुझाव देती हैं? – barrypicker

+0

यह लिखने के लगभग 7 साल हो गए हैं ... लेकिन मुझे लगता है कि 'AssignNewKey' विधि का उद्देश्य एक नया 'सार्वजनिक' * और *' निजी 'कुंजी बनाने के लिए किया गया था, जो डेटाबेस में' सार्वजनिक 'कुंजी को संग्रहीत करते समय संग्रहीत करता था एक्सएमएल स्ट्रिंग के रूप में 'निजी' कुंजी। –

21

RSACryptoServiceProvider(CspParameters) निर्माता एक कुंजीयुग्म जो स्थानीय मशीन पर कीस्ट्रोक में संग्रहित है बनाता है। यदि आपके पास पहले से निर्दिष्ट नाम के साथ एक कीपैयर है, तो यह मौजूदा कीपैयर का उपयोग करता है।

ऐसा लगता है कि आप मशीन पर संग्रहीत कुंजी रखने में रुचि रखते हैं।

तो RSACryptoServiceProvider(Int32) निर्माता का उपयोग करें:

public static void AssignNewKey(){ 
    RSA rsa = new RSACryptoServiceProvider(2048); // Generate a new 2048 bit RSA key 

    string publicPrivateKeyXML = rsa.ToXmlString(true); 
    string publicOnlyKeyXML = rsa.ToXmlString(false); 
    // do stuff with keys... 
} 

संपादित करें:

वैकल्पिक रूप से गलत पर PersistKeyInCsp सेट करने का प्रयास:

public static void AssignNewKey(){ 
    const int PROVIDER_RSA_FULL = 1; 
    const string CONTAINER_NAME = "KeyContainer"; 
    CspParameters cspParams; 
    cspParams = new CspParameters(PROVIDER_RSA_FULL); 
    cspParams.KeyContainerName = CONTAINER_NAME; 
    cspParams.Flags = CspProviderFlags.UseMachineKeyStore; 
    cspParams.ProviderName = "Microsoft Strong Cryptographic Provider"; 
    rsa = new RSACryptoServiceProvider(cspParams); 

    rsa.PersistKeyInCsp = false; 

    string publicPrivateKeyXML = rsa.ToXmlString(true); 
    string publicOnlyKeyXML = rsa.ToXmlString(false); 
    // do stuff with keys... 
} 
+0

सही; मुझे लगता है कि मुझे मशीन पर कुंजी रखने में दिलचस्पी नहीं है। यदि मैं RSACryptoServiceProvider (Int32) कन्स्ट्रक्टर का उपयोग करता हूं तो निम्न कोड मुझे "सिस्टम निर्दिष्ट फ़ाइल नहीं ढूंढ सकता है।" त्रुटि। आरएसए आरएसए = नया आरएसएसीआरपीटी सेवा प्रदाता (2048); rsa.ToXmlString (सत्य); –

+0

चूंकि मैं इसे एएसपीनेट में चला रहा हूं, क्या यह समस्या हो सकती है? –

+0

हां, समस्या शायद इसलिए है क्योंकि "नेटवर्क सेवा" उपयोगकर्ता स्टोर में कुंजी उत्पन्न नहीं कर सकती है। –

115

आप जानते हैं कि हर बार जब आप इस तरह एक कोड का उपयोग करें:

using (var rsa = new RSACryptoServiceProvider(1024)) 
{ 
    // Do something with the key... 
    // Encrypt, export, etc. 
} 

नेट (वास्तव में विंडोज) एक लगातार कुंजी कंटेनर में अपने प्रमुख संग्रहीत करती है - हमेशा के लिए? और वह कंटेनर यादृच्छिक रूप से .NET द्वारा जेनरेट किया गया है ...

परिणाम है:

  1. किसी भी यादृच्छिक RSA/DSA कुंजी आपको भविष्य में डेटा की रक्षा के उद्देश्य के लिए उत्पन्न किया है, कस्टम X.509 प्रमाणपत्र बनाने, आदि विंडोज फाइल सिस्टम में लीक किया गया है । उन सभी के लिए जिनके पास दावा करने के लिए आपके खाते तक पहुंच है। और आपने सोचा था कि आपका डेटा सुरक्षित था ...

  2. आपकी डिस्क धीरे-धीरे डेटा से भरी जा रही है। आम तौर पर एक बड़ी चिंता नहीं है लेकिन यह आपके आवेदन पर निर्भर करती है (उदाहरण के लिए यह हर मिनट सैकड़ों कुंजी उत्पन्न कर सकती है)।

तो क्या आप इस बल्कि अप्रत्याशित व्यवहार से बचने के लिए करते हैं?

using (var rsa = new RSACryptoServiceProvider(1024)) 
{ 
    try 
    { 
     // Do something with the key... 
     // Encrypt, export, etc. 
    } 
    finally 
    { 
     rsa.PersistKeyInCsp = false; 
    } 
} 

हमेशा

अद्यतन:

खुद के लिए देखना चाहते हैं?

इस उपकरण का उपयोग करें http://www.jensign.com/KeyPal/index.html। मेरी मशीन पर मेरे पास हजार है।

+2

मेरे पास ओपी के समान ही आवश्यकता है; सार्वजनिक कुंजी डीबी में जा रही है, निजी कुंजी अंगूठे ड्राइव पर सुरक्षित भंडारण में जा रही है। इसलिए, यदि मैंने आपका उदाहरण कोड इस्तेमाल किया है, लेकिन पहली पंक्ति 'rsa.FromXMLString (pubKey)' थी, तो न तो जेनरेट की गई कुंजी और न ही लोड किया गया स्टोर स्टोर पर कायम रहता है? – KeithS

+0

सीएसपी पैरामीटर() {ध्वज = CspProviderFlags.CreateEphemeralKey} के साथ RSACryptoServiceProvider प्रारंभ करना क्या वही काम करता है? –

+0

आरएसए ऑब्जेक्ट बनाने से पहले PersistKeyInCsp सेट करने का कोई तरीका है? – Nayef

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