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

标签 c# encryption cryptography rsa key

我正在构建一个自定义购物车,其中抄送编号和到期日期将存储在数据库中,直到处理(然后删除)。我需要加密这些数据(显然)。

我想使用 RSACryptoServiceProvider 类。

这是我创建 key 的代码。

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 存储在附加到管理器 key 链的 USB 驱动器上。

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

我的问题是这段代码生成的 key 总是相同的。我如何每次都生成一组唯一的 key ?

更新。我的测试代码如下:
注意:此处的“privatekey”参数为原始私钥。为了更改 key ,我需要验证私钥是否有效。

在 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)将您的 key 永久存储在持久性 key 容器中。 容器由.NET随机生成

这意味着:

  1. 您曾经为保护数据、创建自定义 X.509 证书等目的而生成的任何随机 RSA/DSA key 都可能在您不知情的情况下暴露在 Windows 文件系统中。任何有权访问您帐户的人都可以访问。

  2. 您的磁盘正在慢慢填满数据。通常不是什么大问题,但这取决于您的应用程序(例如,它可能每分钟生成数百个 key )。

要解决这些问题:

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

总是

关于c# - 如何通过 RSA 生成唯一的公钥和私钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1307204/

相关文章:

c# - Observable.Using( ) 取消

c# - 从 List<string> 创建 List<CustomObject>

java - SH256 Java 中的登录密码

java - 是否可以通过 java 中的 bouncycaSTLe 使用 SMIME 加密常规文件

java - 如何使用 AES 方法解密加密列?

解密信用卡号时返回 javax.crypto.IllegalBlockSizeException

security - 马尔罗伊如何在广口 Frog 协议(protocol)中模仿爱丽丝?

c# - 将 Linq 查询连接到 DataTable 并将结果连接到 DataView

c# - 删除时间部分并以不同格式转换日期时间

java - 使用Shamir算法加密数字数据集(约100,000)