69

CC番号と有効期限が処理されるまで(その後削除されるまで)データベースに保存されるカスタムショッピングカートを作成しています。このデータを暗号化する必要があります(明らかに)。

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」パラメーターは元の秘密鍵です。キーを変更するには、秘密キーが有効であることを確認する必要があります。

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

3 に答える 3

134

このようなコードを使用する場合:

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

.NET(実際にはWindows)は、キーを永続キーコンテナに永久に保存します。コンテナは.NETによってランダムに生成されます

これの意味は:

  1. データの保護、カスタム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;
   }
}

いつも

于 2011-04-30T23:00:39.203 に答える
28

コンストラクターは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を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...
}
于 2009-08-20T18:53:10.363 に答える
8

私がやったことは、新しいキーを作成し、コンテナー名と公開キーをデータベースに保存する必要があるときはいつでも、現在のDateTime(DateTime.Now.Ticks.ToString())に基づいて新しいKeyContainer名を作成することです。また、新しいキーを作成するときはいつでも、次のようにします。

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

新しいキーを作成する前に。

于 2009-08-21T20:13:21.880 に答える