如何通过RSA生成唯一的公钥和私钥

我正在build立一个自定义的购物车,其中CC号和出借date将被存储在数据库中,直到处理(然后删除)。 我需要encryption这些数据(显然)。

我想使用RSACryptoServiceProvider类。

这是我的代码来创build我的密钥。

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... } 

现在计划是将私钥xml存储在连接到pipe理器钥匙链的USB驱动器上。

每当经理离开公司时,我希望能够生成新的公钥和私钥(并用新的公钥重新encryption当前存储的所有CC号码)。

我的问题是这个代码生成的密钥总是相同的。 我将如何每次生成一组独特的密钥?

UPDATE。 我的testing代码如下:
注意:这里的“privatekey”参数是原始的私钥。 为了更改密钥,我需要validation私钥是否有效。

在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); } 

你知道每次你使用这样的代码:

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

.NET(实际上是Windows)把你的密钥存储在一个PERSISTENT密钥容器中 – 永远吗? 而那个容器是由.NET随机生成的…

结果是:

  1. 为了保护数据,创build自定义X.509证书等目的而生成的任何随机RSA / DSA密钥已在Windows文件系统中泄漏 。 对于有权访问您帐户的所有人声明。 而且你认为你的数据是安全的

  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 。 我的机器上有几千个

RSACryptoServiceProvider(CspParameters)构造函数创build一个存储在本地计算机密钥库中的密钥对。 如果您已经拥有指定名称的密钥对,则使用现有的密钥对。

听起来好像你对把密钥存储在机器上感兴趣。

所以使用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设置为false:

 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... } 

当我需要创build一个新密钥并将容器名和公钥保存到数据库时,我最终要做的就是根据当前的DateTime(DateTime.Now.Ticks.ToString())创build一个新的KeyContainer名称。 另外,每当我创build一个新的密钥,我会做以下几点:

 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. } 

在创build新密钥之前。