IamDev2013
IamDev2013

Reputation: 51

Construct RSACryptoServiceProvider from public key (not certificate)

I am working on a project where I need to use a "public key" to encrypt a message using RSA algorithm. I was provided with a certificate and my first thought was to use Public Key from that certificate and after investigation I learned I need to use RSACryptoServiceProvider for encryption.

I have checked msdn and only method I thought I should use is RSACryptoServiceProvider.ImportCspBlob(byte[] keyBlob). When I tried to use public key exported from certificate I was getting an error that the header data for certificate is invalid.

I know I can cast X509certificate2.PublicKey.Key to RSACryptoServiceProvider but from what I understood from my client is that going forward I will be given only a public key and not the certificate. This key will have to be saved in .xml configuration file.

So to summarize: Is there a way to generate an RSACryptoServiceProvider given only a certificate's public key?

Upvotes: 3

Views: 4264

Answers (2)

Julian
Julian

Reputation: 31

You can try to look at this example: RSA public key encryption in C#

var publicKey = "<RSAKeyValue><Modulus>21wEnTU+mcD2w0Lfo1Gv4rtcSWsQJQTNa6gio05AOkV/Er9w3Y13Ddo5wGtjJ19402S71HUeN0vbKILLJdRSES5MHSdJPSVrOqdrll/vLXxDxWs/U0UT1c8u6k/Ogx9hTtZxYwoeYqdhDblof3E75d9n2F0Zvf6iTb4cI7j6fMs=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

var testData = Encoding.UTF8.GetBytes("testing");

using ( var rsa = new RSACryptoServiceProvider(1024))
{
    try
    {
        // client encrypting data with public key issued by server
        //
        rsa.FromXmlString(publicKey);
        var encryptedData = rsa.Encrypt(testData, true);

        var base64Encrypted = Convert.ToBase64String(encryptedData);

    }
    finally
    {
        rsa.PersistKeyInCsp = false;
    }
}

Upvotes: 1

Sql Surfer
Sql Surfer

Reputation: 1422

You are OK and following a good typical pattern. The Sender of the data does not need the private key.

The following may confirm some of the code you already have figured out. The one line where I set the private key for the receiver/decoder I left out. I took this from a test case I have in my build deploy stuff.

 byte[] certBytAr;  // This is the certificate as bianry in a .cer file (no  private key in it - public only) 

 X509Certificate2 cert2 = new X509Certificate2(certBytAr);


 string strToEncrypt = "Public To Private Test StackOverFlow PsudeoCode. Surfs Up at Secret Beach.";
 byte[] bytArToEncrypt = Encoding.UTF8.GetBytes(strToEncrypt);

 RSACryptoServiceProvider rsaEncryptor = (RSACryptoServiceProvider)cert2.PublicKey.Key; 

 byte[] dataNowEncryptedArray = rsaEncryptor.Encrypt(bytArToEncrypt, true);

 // done - you now have encrypted bytes 
 // 

  // somewhere elxe ...
 // this should decrpyt it - simulate the destination which will decrypt the data with the private key 

 RSACryptoServiceProvider pk =   // how this is set is complicated 

 // set the private key in the x509 oobject we created way above 
 cert2.PrivateKey = pk; 

 RSACryptoServiceProvider rsaDecryptor = (RSACryptoServiceProvider)cert2.PrivateKey;
 byte[] dataDecrypted = rsaDecryptor.Decrypt(dataNowEncryptedArray, true);

 Console.WriteLine(" encrypt 1 Way Intermediate " + BitConverter.ToString(dataDecrypted));

 string strDecodedFinal = Encoding.UTF8.GetString(dataDecrypted);

 if (strDecodedFinal == strToEncrypt)
 {

 }
 else
 {
     Console.WriteLine(" FAILURE OF  ENCRYPTION ROUND TRIP IN SIMPLE TEST (Direction: Public to Private). No Surfing For You ");
  }

Upvotes: 0

Related Questions