Как создать уникальный открытый и закрытый ключ через RSA



Я создаю пользовательскую корзину покупок, где номера CC и дата Exp будут храниться в базе данных до обработки (затем удаляются). Мне нужно зашифровать эти данные (очевидно).



Я хочу использовать класс 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...
}


теперь планируется хранить закрытый ключ xml на USB-накопителе, подключенном к цепочке ключей менеджеров.



всякий раз, когда менеджер покидает компанию, я хочу иметь возможность для создания новых открытых и закрытых ключей (и повторного шифрования всех сохраненных в настоящее время номеров CC с новым открытым ключом).



моя проблема заключается в том, что ключи, сгенерированные этим кодом всегда одинаковы. Как бы я генерировал уникальный набор ключей каждый раз?



обновление. мой тестовый код ниже.:
Примечание: параметр "privatekey" здесь является исходным закрытым ключом. Для того, чтобы ключи были изменены, мне нужно проверить, что закрытый ключ действительный.



По Умолчанию.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);
}
735   3  

3 ответов:

когда вы используете такой код:

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

.NET (на самом деле Windows) хранит ваш ключ в постоянные контейнер ключей навсегда. Контейнер генерируется случайным образом .NET

это значит:

  1. любой случайный ключ RSA/DSA, который вы когда-либо создавали для защиты данных, создания пользовательского сертификата X. 509 и т. д. возможно, были открыты без вашего ведома в файловой системе Windows. Доступно для всех, кто имеет доступ к вашей учетной записи.

  2. ваш диск медленно заполняется данными. Обычно это не большая проблема, но это зависит от вашего приложения (например, он может генерировать сотни ключей каждую минуту).

чтобы решить эти проблемы:

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

всегда

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

EDIT:

в качестве альтернативы попробуйте установить 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...
}

в итоге я создал новое имя KeyContainer на основе текущего DateTime (DateTime.Сейчас.Галочки.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.
}

перед созданием нового ключа.

Comments

    Ничего не найдено.