I'm using RSA for my asymmetric encryption in C#. I use RSACryptoServiceProvider.
I want to know how RSACryptoServiceProvider chooses which key (public or private) to use during encrypting. I need to know this because there are times that I would need to encrypt using the public key (exponent, modulus) and there are times when I need to encrypt using the private key (D, modulus).
I've looked into the documentation and other online sources but I can't find answers.
I've tried to experiment by swapping some of the parameters with each other. Didn't work. I've also tried importing incomplete and complete parameters.
Here's some of my code:
public class myRSA
{
private System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
private RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
private static string modPath = "C:\\rsaHamster\\mod.txt";
private static string expoPath = "C:\\rsaHamster\\expo.txt";
private static string dPath = "C:\\rsaHamster\\D.txt";
private static string dpPath = "C:\\rsaHamster\\dp.txt";
private static string dqPath = "C:\\rsaHamster\\dq.txt";
private static string pPath = "C:\\rsaHamster\\p.txt";
private static string qPath = "C:\\rsaHamster\\q.txt";
private static string inverseQPath = "C:\\rsaHamster\\inverseq.txt";
public void export()
{
RSACryptoServiceProvider rsaExport = new RSACryptoServiceProvider();
RSAParameters rsaParam = new RSAParameters();
rsaParam = rsaExport.ExportParameters(true);
fileMgr.write(rsaParam.Modulus,modPath);
fileMgr.write(rsaParam.Exponent,expoPath);
fileMgr.write(rsaParam.D,dPath);
fileMgr.write(rsaParam.DP, dpPath);
fileMgr.write(rsaParam.DQ, dqPath);
fileMgr.write(rsaParam.P, pPath);
fileMgr.write(rsaParam.Q, qPath);
fileMgr.write(rsaParam.InverseQ, inverseQPath);
}
/* TRUE = use private key for encryption, FALSE = use public key for encryption */
public RSAParameters import(bool check)
{
RSAParameters rsaParam = new RSAParameters();
byte[] mod = fileMgr.read(modPath);
byte[] expo = fileMgr.read(expoPath);
byte[] D = fileMgr.read(dPath);
byte[] dp = fileMgr.read(dpPath);
byte[] dq = fileMgr.read(dqPath);
byte[] p = fileMgr.read(pPath);
byte[] q = fileMgr.read(qPath);
byte[] inverseQ = fileMgr.read(inverseQPath);
if (check == true)
{
rsaParam.D = D;
rsaParam.Exponent = expo;
rsaParam.Modulus = mod;
rsaParam.DP = dp;
rsaParam.DQ = dq;
rsaParam.P = p;
rsaParam.Q = q;
rsaParam.InverseQ = inverseQ;
}
else if (check == false)
{
//rsaParam.D = expo;
rsaParam.Exponent = expo;
rsaParam.Modulus = mod;
/*
rsaParam.DP = dp;
rsaParam.DQ = dq;
rsaParam.P = p;
rsaParam.Q = q;
rsaParam.InverseQ = inverseQ;
*/
}
return rsaParam;
}
public byte[] encryptUsingPublic(string msg)
{
RSACryptoServiceProvider pubRsa = new RSACryptoServiceProvider();
RSAParameters rsaParam = new RSAParameters();
rsaParam = this.import(false);
pubRsa.ImportParameters(rsaParam);
Byte[] data = encoding.GetBytes(msg);
Byte[] encrypted = pubRsa.Encrypt(data, false);
return encrypted;
}
/* Message is encrypted using Public Key(Exponent,Modulus) */
public byte[] decryptUsingPrivate(byte[] cipher)
{
RSACryptoServiceProvider decRsa = new RSACryptoServiceProvider();
RSAParameters rsaParam = new RSAParameters();
rsaParam = this.import(true);
decRsa.ImportParameters(rsaParam);
byte[] plain;
plain = decRsa.Decrypt(cipher, false);
return plain;
}
public byte[] encryptUsingPrivate(string msg)
{
RSACryptoServiceProvider privRsa = new RSACryptoServiceProvider();
RSAParameters rsaParam = new RSAParameters();
rsaParam = this.import(true);
privRsa.ImportParameters(rsaParam);
Byte[] data = encoding.GetBytes(msg);
Byte[] encrypted = privRsa.Encrypt(data, false);
return encrypted;
}
/* Message is encrypted using Private Key(D,Modulus) */
public byte[] decryptUsingPublic(byte[] cipher)
{
RSACryptoServiceProvider decRsa = new RSACryptoServiceProvider();
RSAParameters rsaParam = new RSAParameters();
rsaParam = this.import(false);
decRsa.ImportParameters(rsaParam);
byte[] plain;
plain = decRsa.Decrypt(cipher, false);
return plain;
}
}
class MainProg
{
public static void Main(string[] args)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
myRSA myrsa = new myRSA();
myrsa.export();
Console.Write("Enter string to be encrypted: ");
string msg = Console.ReadLine();
string val = null;
Console.WriteLine();
while (val != "c")
{
Console.WriteLine("a. Encrypt using Public then Decrypt using Private (challenge)");
Console.WriteLine("b. Encrypt using Private then Decrypt using Public (key exchange)");
Console.WriteLine("c. Exit");
val = Console.ReadLine();
if (val == "a")
{
byte[] encrypted = myrsa.encryptUsingPublic(msg);
Console.Write("\nEncrypted msg is: ");
Console.WriteLine(encoding.GetString(encrypted));
Console.WriteLine();
byte[] decrypted = myrsa.decryptUsingPrivate(encrypted);
}
else if (val == "b")
{
byte[] encrypted = myrsa.encryptUsingPrivate(msg);
Console.Write("\nEncrypted msg is: ");
Console.WriteLine(encoding.GetString(encrypted));
Console.WriteLine();
byte[] decrypted = myrsa.decryptUsingPublic(encrypted);
}
}
Console.Read();
}
}
I've highlighted the import command in my decryptUsingPublic method. The parameter is set to false since I only need to import the Modulus and Exponent parameters because I'm going to decrypt using the public key only. But if I do this (set parameter to false), I get a bad key error. Now if I set it to true, the error disappears. Now if setting the parameter to true removes the error, I'm no longer sure if the Decrypt function of RSA uses the public key!
I did a simple experiment on RSA. Here's the code:
RSACryptoServiceProvider fRsa = new RSACryptoServiceProvider();
RSACryptoServiceProvider sRsa = new RSACryptoServiceProvider();
RSAParameters param = new RSAParameters();
param = fRsa.ExportParameters(false);
byte[] enc = fRsa.Encrypt(encoding.GetBytes(msg), false);
sRsa.ImportParameters(param);
byte[] dec = sRsa.Decrypt(enc, false);
What this does, basically is initialize two instances of RSA. for the first, I export the public parameters only. I encrypt msg using the first instance of RSA. I use the second RSA and import the parameters of the first to the second. Then I decrypt the cipher of msg using the second. When I do this, the program gives me a Bad Key error. I think it would mean that the first RSA encrypted the msg using the public key since the second RSA, having only the public key imported to it, cannot decrypt the cipher.
So, how do I make RSA encrypt using the private key? I'm sorry if my presentation is fuzzy or incomplete. Please ask any questions if it helps you help me.
Hoping for a response from you guys!