14

I'm trying to initialize RSACryptoServiceProvider with my own public and private keys.

As far as I could research, the way to do this is to call the constructor with

RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(cspParams);

cspParams as shown above. However, when I look at the msdn example on the use of it: http://msdn.microsoft.com/en-us/library/ca5htw4f.aspx

I don't see any place where they set the private or public keys. Only using a KeyContainer. When I create an RSACryptoServiceProvider without a cspParam, then it is by default set to only use a Public key. I notice this when I check the PublicOnly variable on the class itself and it is a read only variable.

My question is how do I initialize this class and then set my own private and public keys. The server will be using the private key and the client will have the public key.

What I found out is that creating an RSAParameter object and setting the .Exponent and .Modulus parameters on it as the public and private variables respectively.

But I'm getting a "Missing Private Key" error since I believe the RSACryptoServiceProvider isn't initialized with the correct constructor.

Below is some of my code. Don't worry about BigInteger class, it's just an experiment. Even if I use it or not, I get the same error.

//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);
//}
C0D3
  • 6,440
  • 8
  • 43
  • 67
  • The public key is defined by the Exponent and Modulus of the RSA Params. The private key, is D in the RSAParameters class – craig1231 Nov 30 '12 at 23:08
  • So, how do I set the public key of the RSAParameter then? I already have my public key, just gotta set the RSAParameter object so that I can use it. – C0D3 Nov 30 '12 at 23:13
  • Depends if you have a public and a private key to use, if not then you can use CSPParams to create a pair. – craig1231 Nov 30 '12 at 23:23
  • I do, can you tell me how to use them? – C0D3 Nov 30 '12 at 23:24
  • OK the public key would consist of the Exponent and Modulus, how is the public key stored? – craig1231 Nov 30 '12 at 23:25
  • It is just in a string variable – C0D3 Nov 30 '12 at 23:26
  • 1
    let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20419/discussion-between-c0d3junk13-and-craig1231) – C0D3 Nov 30 '12 at 23:28
  • Will test and see if this works. http://blogs.msdn.com/b/alejacma/archive/2008/10/23/how-to-generate-key-pairs-encrypt-and-decrypt-data-with-net-c.aspx – C0D3 Dec 01 '12 at 00:04

2 Answers2

22

The fields are horribly named and it is confusing you. The Exponent field is really the public exponent for a public key. The private exponent for a private key is the D field.

It is not your fault that MSDN documentation sucks.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • Yep, those variables are terribly named. Let me try that and get back to you. Thanks! – C0D3 Nov 30 '12 at 23:11
  • Now, I'm getting a missing modulus error. Any idea what that means? Or what do I need to set the Modulus variable to? Does this mean I don't need to initialize with cspParams? – C0D3 Nov 30 '12 at 23:12
  • 2
    The modulus is ... the modulus. If you look at an [`RSAParameters`](http://msdn.microsoft.com/en-us/library/ke2te33h.aspx) structure your RSA public key only has the Modulus and Exponent fields but the RSA private has *all* the fields. – President James K. Polk Nov 30 '12 at 23:25
  • I didn't end up doing what I needed to do this way (I used Bouncy Castle) but you were right. And I did manage to do encrypt and decrypt just with RSACryptoServiceProvider of msdn. – C0D3 Apr 09 '13 at 12:01
0

You have to convert base 64:

byte[] modulusBytes = Convert.FromBase64String(modulus);
byte[] exponentBytes = Convert.FromBase64String(exponent);
René Wolferink
  • 3,558
  • 2
  • 29
  • 43