RSACryptoServiceProvider 用自己的公钥和私钥初始化

Posted

技术标签:

【中文标题】RSACryptoServiceProvider 用自己的公钥和私钥初始化【英文标题】:RSACryptoServiceProvider initialize with own public key and private key 【发布时间】:2012-11-19 05:10:48 【问题描述】:

我正在尝试使用我自己的公钥和私钥初始化 RSACryptoServiceProvider。

据我所知,这样做的方法是使用

调用构造函数
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(cspParams);

cspParams 如上所示。但是,当我查看有关使用它的 msdn 示例时: http://msdn.microsoft.com/en-us/library/ca5htw4f.aspx

我没有看到他们设置私钥或公钥的任何地方。仅使用 KeyContainer。当我创建一个没有 cspParam 的 RSACryptoServiceProvider 时,它默认设置为仅使用公钥。当我检查类本身的 PublicOnly 变量时,我注意到了这一点,它是一个只读变量。

我的问题是如何初始化这个类,然后设置我自己的私钥和公钥。 服务器将使用私钥,客户端将拥有公钥。

我发现创建一个 RSAParameter 对象并将其上的 .Exponent 和 .Modulus 参数分别设置为公共和私有变量。

但我收到 "Missing Private Key" 错误,因为我认为 RSACryptoServiceProvider 未使用正确的构造函数进行初始化。

以下是我的一些代码。不用担心 BigInteger 类,这只是一个实验。不管我是否使用它,我都会得到同样的错误。

//Create a UnicodeEncoder to convert between byte array and string.
UnicodeEncoding ByteConverter = new UnicodeEncoding();

byte[] dataToEncrypt = ByteConverter.GetBytes(password);
byte[] encryptedData;
byte[] decryptedData;

//RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters rsap = new RSAParameters();

BigInteger n = new BigInteger("19579160939939334264971282204525611731944172893619019759209712156289528980860378672033164235760825723282900348193871051950190013953658941960463089031452404364269503721476236241284015792700835264262839734314564696723261501877759107784604657504350348081273959965406686529089170062268136253938904906635532824296510859016002105655690559115059267476786307037941751235763572931501055146976797606538425089134251611194500570922973015579287289778637105402129208324300035518642730384616767241853993887666288072512402523498267733725021939287517009966986976768028023180137546958580922532786773172365428677544232641888174470601681", 10);

BigInteger e = new BigInteger("65537", 10);

//rsap.Modulus = ByteConverter.GetBytes(publicKey);
rsap.Exponent = e.getBytes();
rsap.Modulus = n.getBytes();
  /*rsap.Exponent = ByteConverter.GetBytes(publicKey);
    rsap.D = ByteConverter.GetBytes(publicKey);
    rsap.DP = ByteConverter.GetBytes(publicKey);
    rsap.DQ = ByteConverter.GetBytes(publicKey);
    rsap.P = ByteConverter.GetBytes(publicKey);
    rsap.Q = ByteConverter.GetBytes(publicKey);
    rsap.InverseQ = ByteConverter.GetBytes(publicKey);*/

using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())

    //RSA.PublicOnly = false;

    RSA.ImportParameters(rsap);

    Debug.Log ("PublicOnly: " + RSA.PublicOnly);

    Debug.Log (rsap.Modulus.Length);
    //Debug.Log (RSA.ToString());
        //Pass the data to ENCRYPT, the public key information  
        //(using RSACryptoServiceProvider.ExportParameters(false), 
        //and a boolean flag specifying no OAEP padding.
        //encryptedData = RSACSPSample.RSAEncrypt(dataToEncrypt, rsap, false);
        encryptedData = RSACSPSample.RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false), false);


        Debug.Log ("encryptedData: " + encryptedData);
        //Display the decrypted plaintext to the console. 
        //Debug.Log("Decrypted plaintext: " + ByteConverter.GetString(""));

        //Pass the data to DECRYPT, the private key information  
        //(using RSACryptoServiceProvider.ExportParameters(true), 
        //and a boolean flag specifying no OAEP padding.
        decryptedData = RSACSPSample.RSADecrypt(encryptedData, RSA.ExportParameters(true), false);



//encryptedData = RSACSPSample.RSAEncrypt(dataToEncrypt, rsap, false);

//if (encryptedData != null) 
    password = ByteConverter.GetString(decryptedData);
//

【问题讨论】:

公钥由 RSA 参数的指数和模数定义。私钥,是RSAParameters类中的D 那么,如何设置 RSAParameter 的公钥呢?我已经有了我的公钥,只需设置 RSAParameter 对象以便我可以使用它。 取决于你是否有公钥和私钥可以使用,如果没有,你可以使用 CSPParams 来创建一对。 我知道,你能告诉我如何使用它们吗? 让我们continue this discussion in chat 【参考方案1】:

这些字段的名字很可怕,让您感到困惑。 Exponent 字段实际上是公钥的 public 指数。私钥的 private 指数是 D 字段。

MSDN 文档很烂不是你的错。

【讨论】:

是的,这些变量的名字很糟糕。让我试试,然后回复你。谢谢! 现在,我收到一个缺少模数的错误。知道这意味着什么吗?或者我需要将 Modulus 变量设置为什么?这是否意味着我不需要使用 cspParams 进行初始化? 模数是……模数。如果您查看RSAParameters 结构,您的 RSA 公钥只有 Modulus 和 Exponent 字段,但 RSA private 有所有字段。 我最终并没有以这种方式完成我需要做的事情(我使用了 Bouncy Castle),但你是对的。而且我确实设法仅使用 msdn 的 RSACryptoServiceProvider 进行加密和解密。【参考方案2】:

你必须转换base 64:

byte[] modulusBytes = Convert.FromBase64String(modulus);
byte[] exponentBytes = Convert.FromBase64String(exponent);

【讨论】:

以上是关于RSACryptoServiceProvider 用自己的公钥和私钥初始化的主要内容,如果未能解决你的问题,请参考以下文章

RSACryptoServiceProvider 工作正常吗?

如何使用先前使用 RSACryptoServiceProvider 加密的 RSACng 解密数据

如何提取 RSACryptoServiceProvider 生成的素数?

C# - RSACryptoServiceProvider - 错误:错误数据

从公钥正确创建 RSACryptoServiceProvider

这个 C# RSACryptoServiceProvider 方法的红宝石等价物是啥