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...
}
計画では、マネージャーのキーチェーンに接続されたUSBドライブに秘密キーxmlを保存します。
マネージャーが退職するたびに、新しい公開キーと秘密キーを生成できるようにしたい(そして、現在保存されているすべてのCC番号を新しい公開キーで再暗号化する)。
私の問題は、このコードによって生成されるキーが常に同じであることです。毎回一意のキーセットを生成するにはどうすればよいですか?
PDATE。私のテストコードは以下のとおりです。
注:ここの「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);
}
私がやったことは、新しいキーを作成し、コンテナ名と公開キーをデータベースに保存する必要があるときはいつでも、現在の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.
}
新しいキーを作成する前に。
このようなコードを使用する場合:
using (var rsa = new RSACryptoServiceProvider(1024))
{
// Do something with the key...
// Encrypt, export, etc.
}
.NET(実際にはWindows)は、キーをpersistentキーコンテナに永久に保存します。コンテナは.NETによってランダムに生成されます
これの意味は:
データの保護、カスタムX.509証明書の作成などの目的でこれまでに生成したランダムなRSA/DSAキーは、Windowsファイルシステムを意識せずに公開されている可能性があります。アカウントにアクセスできる人なら誰でもアクセスできます。
ディスクはゆっくりとデータで満たされています。通常は大きな問題ではありませんが、アプリケーションによって異なります(たとえば、毎分数百のキーを生成する場合があります)。
これらの問題を解決するには:
using (var rsa = new RSACryptoServiceProvider(1024))
{
try
{
// Do something with the key...
// Encrypt, export, etc.
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
[〜#〜] always [〜#〜]
RSACryptoServiceProvider(CspParameters)
コンストラクターは、ローカルマシンのキーストアに保存されるキーペアを作成します。指定した名前のキーペアが既にある場合は、既存のキーペアが使用されます。
マシンにキーを保存することに興味があるnotのように聞こえます。
したがって、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...
}