1

I want to implement a scenario where two endpoints can securely communicate with each other using public/private key encryption. The scenario is following:

For A to send a message to B:

A encrypts the message using A's private key.

A encrypts the message using B's public key.

A sends the message.

B receives the message.

B decrypts the message using A's public key.

B decrypts the message using B's private key.

B reads the message.

Here is what I have in C# using RSA encryption:

// Alice wants to send a message to Bob:

String plainText = "Hello, World!";
Byte[] plainData = Encoding.Default.GetBytes(plainText);
Byte[] cipherData = null;

RSACryptoServiceProvider alice = new RSACryptoServiceProvider();
RSACryptoServiceProvider bob = new RSACryptoServiceProvider();

var alicePrivateKey = alice.ExportParameters(true);
var alicePublicKey = alice.ExportParameters(false);

var bobPrivateKey = bob.ExportParameters(true);
var bobPublicKey = bob.ExportParameters(false);

RSACryptoServiceProvider messenger = new RSACryptoServiceProvider();
        
messenger.ImportParameters(alicePrivateKey);
cipherData = messenger.Encrypt(plainData, true);

messenger.ImportParameters(bobPublicKey);
cipherData = messenger.Encrypt(cipherData, true);

messenger.ImportParameters(alicePublicKey);
cipherData = messenger.Decrypt(cipherData, true);

messenger.ImportParameters(bobPrivateKey);
cipherData = messenger.Decrypt(cipherData, true);            

String result = Encoding.Default.GetString(alice.Decrypt(cipherData, true));

Clearly, there is something wrong with the following lines:

messenger.ImportParameters(bobPublicKey);
cipherData = messenger.Encrypt(cipherData, true);

Which throws System.Security.Cryptography.CryptographyException with message { "Bad Length" }.

As I can see it is not able to encrypt the data using just the public part of bob's key.

Can someone throw some light on how to properly accomplish what I want to do in C#?

Community
  • 1
  • 1

2 Answers2

4

Two problems here:

A) Your protocol design is wrong. If you want to use RSA to exchange messages, the algorithm is this:

A encrypts message using B's public key

A sends the message

B decrypts the message using B's private key

(B does processing)

B encrypts message using A's public key

B sends the message

A decrypts the message using A's private key

and so on. Notice how A does not know B's private key, and vice versa. The public and private keys are related in such a way that a message encrypted with a public key (known to everyone) can only be decrypted with the corresponding private key (known only to the intendent recipient of the encrypted message). This is the whole point of RSA, actually.

As for implementation in C#, it is quite trivial to do with the Crypto classes once you really understand the underlying concepts. See for example here and here.

B) RSA is good for exchanging small amounts of data. It is meant for key exchange over an insecure channel without the need for a shared secret. For exchanging "normal" data, a symmetric algorithm such as AES is used. So the idea would be generating a random passphrase and IV from A, and sending that to B via RSA as discussed in A; after both parties know the passphrase and IV, they can just encrypt data using AES with the shared key.

This is what SSL does, and you should have a really good reason to roll your own instead of using a standard SSL stream.

axel_c
  • 6,557
  • 2
  • 28
  • 41
  • *"Notice how A does not know B's private key, and vice versa."* - I agree. But, notice how A does not try to access B's private key. A encrypts the message using 1) B's public key so that B can decrypt using its private key and 2) A's private key so that B can decrypt using A's public key and make sure it came from A. – Sharp.Extensions Mar 23 '12 at 09:21
  • I know *SSL* and I prefer using it over any custom implementation. But, in my case, I am trying to create a working prototype that works for secure IPC communication. My prototype is targeting a single machine scenario. – Sharp.Extensions Mar 23 '12 at 09:28
  • But you're saying 'A encrypts X using A's private key' - that's not the way it works. The public key is used for encryption, the private one for decryption. – axel_c Mar 23 '12 at 09:36
  • Ok. I am not have used the correct term. Perhaps that is called signing? That ensures that the message is sent by A. – Sharp.Extensions Mar 23 '12 at 10:50
  • 1
    The double encryption (in the question) means there is an implicit signature (based on encryption with A's private key). – H H Mar 23 '12 at 11:37
  • Too, bad I can't vote up, need 15 points. :(. But, thanks for your help. – Sharp.Extensions Mar 23 '12 at 12:00
  • 2
    It is perfectly legal for Alice to encrypt the message with Alice's private key and then Bob's public key. When Bob decrypts the message with his private key, he knows that only he could read the message. When he decrypts the resulting message with Alice's public key, he knows it came from Alice. Normally however Alice would instead *hash* the message, sign the *hash* with her private key, and then send the signed hash to Bob. – Eric Lippert Mar 23 '12 at 14:50
1

RSA is used to encrypt data which are smaller than the key. You use symmetric key to encrypt large amount of data and then use the RSA to share the symmetric key.

For further details you might refer to this question : how to use RSA to encrypt files (huge data) in C#

Community
  • 1
  • 1
Manoj
  • 5,011
  • 12
  • 52
  • 76