You might get a high CPU usage while decrypting using RSA keys

You might get a high CPU usage while decrypting using RSA keys

 

 

The root cause of this issue (high CPU usage while decrypting using RSA keys) is as stated in the MSDN link https://msdn.microsoft.com/en-us/magazine/cc163676.aspx. The name of the article is Encrypting without Secrets” by Keith Brown.

The points to look at this article are (the below text is directly copied from the above link and is the writing of the Keith Brown the author of the article “ Encrypting without Secrets”):

Key Size

The size of the key you generate impacts the level of security and inversely, the performance you'll get from the cryptosystem. Also, the longer the key you choose, the longer it'll take to generate in Key Manager. In a Virtual PC environment running on a reasonably fast machine, a 4096-bit key takes several seconds to generate, while a 16384-bit key takes several minutes! At the moment, Key Manager creates these keys on the user interface thread, which was expedient for a sample app, but an obvious improvement would be to generate the key asynchronously so the UI doesn't freeze up. Regardless of how long it takes to create the key pair, what you should care about is the security and performance trade-off at run time, so I ran some tests to time encryption and decryption using the five key sizes that Key Manager supports (see Figure 3).

Figure 3 Key Size and Runtime Performance 

Pay attention to the units in Figure 3. Encryption is measured in milliseconds, but decryption is measured in seconds. Private key operations are not cheap in RSA. If performance is critical, you can purchase specialized hardware to offload encryption and/or decryption from the main CPU, dramatically increasing performance without sacrificing security. This will require an alternate CSP, which will require a bit of tweaking of my code, but that's a small price to pay for the performance benefit you'll see. From a security perspective, current recommendations are to stick with RSA keys that are at least 2048 bits long as an absolute minimum; 4096 bits seems to be the sweet spot in the performance/security curve today. And in the future, you can go even higher. As you can see from Figure 3, my own tests include keys up to 16384 bits long.

Please take a look at the above two graphs. To generate a key pair for decryption it takes up to seconds of time compared to generating the key pairs for encryption. This is exactly what is happening in this situation.

The second point to note in this article is:

Decryptor.Decrypt unwinds the data structure by first peeling off the key container name and constructing an RSACryptoServiceProvider instance bound to that key container. It then decodes the base64-encoded payload and peels off the encrypted AES key, decrypting it using RSACryptoServiceProvider.Decrypt. That step is likely the most CPU-intensive part of the entire process if you're encrypting relatively small strings.

Considering all these the remedy is to reduce the RSA key length, if the string to encrypt and decrypt is relatively small in the application.

To do this you could use RSACryptoServiceProvider class constructor to set the key length as shown below.

RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(384);

Also note that the RSACryptoServiceProvider supports key lengths from 384 bits to 16384 bits in increments of 8 bits if you have the Microsoft Enhanced Cryptographic Provider installed. It supports key lengths from 384 bits to 512 bits in increments of 8 bits if you have the Microsoft Base Cryptographic Provider installed.

We might consider reducing the key length to as small as possible in order to reduce the key pair generation time.

The second workaround is to use named key containers and use that key container every time when you are encrypting and decrypting data.

References:

https://msdn.microsoft.com/en-us/library/zseyf239.aspx

https://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.keysize.aspx

-Shamik