1
votes

I found several solutions where I can use the RSA Provider to Encrypt a message with the public key and Decrypt it with the private one.

But what I want to have is to Encrypt with the private key and Decrypt with the public key.

I want to store the public key in my app and encrypt a license for example on my dev machine with the private key, send it to the app and let the information decrypt with a public key.

How can I achieve that?

2
What use is it to encrypt something which can be decrypted using a public key??Ian
You should explain why using RSA as intended (i.e. the only reliable way) is not fit for purpose so you can get suggestion on how to make it so.Alex K.
It is better to refer to this scenario as RSA "signing" and "verifying" rather than RSA encryption and decryption. Using the correct terminology will also help you find the right classes, the right documentation, and the right examples.President James K. Polk
Are there more than one application? Or you just want to communicate only between the dev machine and the application?kelalaka

2 Answers

2
votes

There are two main possibilities here:

1) You actually are referring to signing (a private key operation) and verification (a public key operation).

In RSA signing, the input message is digested, and the digest is combined with a padding scheme, then the private key applied to the padded data.

In RSA verification, the candidate message is digested, the public key is used to undo the private key application, and then the digest is used to validate the padded message. (In PKCS#1 signatures that's "look and see if it's the right answer", for PSS it's more complicated).

If this is what you mean, then you want

  • Signing
    • RSA.SignData (hashes the data, then calls SignHash)
    • RSA.SignHash (completes the operation, is public in case you already hashed the data and want to save on redundancy)
  • Verification
    • RSA.VerifyData (hashes the data, then calls VerifyHash)
    • RSA.VerifyHash (same as above)

2) You want to encapsulate arbitrary data in a transformation using the private key.

The RSA PKCS#1 standards and/or RFCs have no description of what this means. "Encrypt", in RSA, means to apply a chosen padding scheme to the data (PKCS#1 or OAEP) then perform the RSA operation with the public key. "Decrypt" means to perform the RSA operation using the private key, then remove the padding.

The built-in Encrypt and Decrypt methods are performing these operations, including knowing which key to use.

Applying the keys backwards would produce sensible results mathematically, but it doesn't make sense in practice. Assuming we keep "private" meaning "the key that is only known by one party", this means that you have data that is produced by one person that can be read by anyone. If the idea is "I want the readers to know that it was produced by [the private key holder]", then signing is a better operation: It leaves the data in plain form, letting readers do a more optimal read.

RSA encryption is further only defined as a one-shot operation, which means that as a consequence it is limited to a total number of content bytes that is less than the number of bytes in the RSA modulus (11 bytes less for PKCS#1, and bigger reductions in OAEP, depending on the chosen OAEP hash algorithm). Because signing hashes first, the amount of data being processed in RSA is of fixed size. In the normal RSA encryption case the thing being encrypted is a symmetric (AES) key, or some means of building an AES key... and that's much smaller.

In the end, the conclusion of this path is "No, .NET does not allow you to do this".


If you're transporting a license, the industry-standard approach is to sign it. Remember to include a mechanism for replacing the license-issuer key over time, such as writing down the signing certificate. Or use something like PKCS#7/CMS Signed Data, as exposed in .NET by System.Security.Cryptography.Pkcs.SignedCms, since it is a predefined format for transporting the data, signature, and signing certificates -- just check that cms.SignerInfos[0].Certificate is acceptable, and then if CheckSignature(true) doesn't throw, you're good to go.

0
votes

Encrypting with the private key is signing. Some providers have a verify function that gives the decrypted signature rather than just verifying it.