RSACryptoServiceProvider initialize with own public key and private key
Asked Answered
T

2

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);
//}
Tripedal answered 30/11, 2012 at 22:59 Comment(8)
The public key is defined by the Exponent and Modulus of the RSA Params. The private key, is D in the RSAParameters classHols
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.Tripedal
Depends if you have a public and a private key to use, if not then you can use CSPParams to create a pair.Hols
I do, can you tell me how to use them?Tripedal
OK the public key would consist of the Exponent and Modulus, how is the public key stored?Hols
It is just in a string variableTripedal
let us continue this discussion in chatTripedal
Will test and see if this works. blogs.msdn.com/b/alejacma/archive/2008/10/23/…Tripedal
B
24

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.

Binnacle answered 30/11, 2012 at 23:7 Comment(4)
Yep, those variables are terribly named. Let me try that and get back to you. Thanks!Tripedal
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?Tripedal
The modulus is ... the modulus. If you look at an RSAParameters structure your RSA public key only has the Modulus and Exponent fields but the RSA private has all the fields.Binnacle
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.Tripedal
C
0

You have to convert base 64:

byte[] modulusBytes = Convert.FromBase64String(modulus);
byte[] exponentBytes = Convert.FromBase64String(exponent);
Considered answered 30/10, 2015 at 12:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.