Why cripple the .NET RSA implementation?

I just found out that RSACryptoServiceProvider, the RSA implementation in .NET, does not allow you to use a private key to encrypt data. I’m no cryptographic expert, but I do know how asymmetric key algorithms like RSA work, and that you can use a private key for encryption. That’s how signing works. But why cripple the implementation and limit it to just signing?

The rationale is in the common application of public-key cryptography, where:

  • Encrypting with the public key ensures confidentiality, i.e. the process known as encryption in common tongue. Encrypting with a public key ensures that only the entity in possession of the private key can read the data.
  • Encrypting with the private key ensures authenticity, i.e. the process known as signing in common tongue. There is no need to encrypt the entire data stream to ensure authenticity, so the common approach is to calculate a hash of the data and sign the hash instead.

To facilitate these patterns, the .NET public-key cryptography API is designed so that:

  • Encrypt() encrypts with a public key, Decrypt() requires a private key.
  • SignData() encrypts with a private key, but since that implies a signature, one must provide a hashing algorithm and a private key. VerifyData() uses a public key.

But I want to encrypt with my private key! Yes, this is what SignData() does, but it does so to just the hash calculated by the provided hashing algorithm, since that is the de-facto approach for signing, and implementing my own HashAlgorithm that passes in all the data is just wrong.

OK, these are the common uses, but why limit the API to that? There is no limitation in the RSA algorithm to my knowledge that prevents other uses than the two offered by RSACryptoServiceProvider. In fact, if I wanted to perform the traditional signing approach, I could just hash the data myself and encrypt it with my private key myself. Or even better, SignData() could be available to help me for convenience.

So, how do you apply RSA in .NET in an uncommon manner? Don’t use .NET’s cryptography API, but embrace an open source alternatives like BouncyCastle, which saves your day.

This entry was posted in C#, Technical. Bookmark the permalink.

8 Responses to Why cripple the .NET RSA implementation?

  1. I think because RSA private key encryption for a longer string is very slow.

  2. Hi,

    I believe Jingsong’s argument is correct. Asymmetric chiphers is ideal for solving the key sharing problem – but is not suitable for encryption of large amounts of data since they are quite CPU-intensive in computation.

    The way it works is that a shared secret – a key for the symmetric chipher – is encrypted with the asymmetric chipher – in this case RSA – and sent to the recipient. The recipient decrypts the shared secrets and uses it to decrypt the actual data.

    To validate authenticity a keyed or unkeyed hashing algorithm is applied; SHA-* is the most commonly used unkeyed algorithms used nowadays – and this hash is signed. .SignData(…) does this for you in the .NET crypto API.

    –larsw

  3. Håvard says:

    Hi Lars and Jingsong,

    Your arguments and points are indeed correct. My point is that only allowing hash signing with the private key is an artificial limitation, since the real limitation lies in the time required to encrypt a relatively large amount of data using the private key.

    It is my opinion that the API should not protect you, or limit you, if you will, from doing something that is valid to do, although the usual approach is different. I apologize if my post implied something else than this.

  4. Antonio says:

    Hi Håvard,

    I very much agree, I’m a bit frustrated by this aspect of the .net implementation myself. I’m working on a project that deals with ensuring the authenticity of information on ATM smart cards, which have sensitive data on them encrypted with a CA private key to ensure authenticity, so i need to be able to decrypt with the public key. Sign/verify just isn’t what I need, since I’m not the one putting the data on the cards.

    I’ve had a look at bouncycastle, but i found the library to be a bit hard to work with, due to the abundance of classes and the lack of documenation.

    Could you pls provide a few lines of example code for decryption with a public key using bublycastle? TIA!

  5. Håvard says:

    Hi Antonio. I wrote a quick post on using BouncyCastle for RSA. Take a look at RSA using BouncyCastle. Hope it helps!

  6. Antonio says:

    Hi Håvard,

    I ended up implementing RSA myself the same day I posted my question to you, but thanx anyway:) The implementation was trivial, RSA is explained well on wikipedia and the algorithm amounts to a single few-letter formula. All that’s needed besides the formula is an implementation of BigInteger(to represent the encrypted text and the key), which I found on codeproject(a very good one i might add, by a chap called Chew Keong TAN – he’s Danish apparently:))

    Anyway, just wanted to say thanks for posting the “RSA using BouncyCastle” (now that I see the code it seems simple:)) even tho i didn’t end up using it.

  7. innocent bystander says:

    thank you for your post – I had exactly the same problem

  8. Abhinav says:

    I’m facing the same problem. Did not want to implement and maintain RSA in my code, and could not find an opensource alternative.

    Lets see how Bouncy Castle works out!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>