C# RSA Encrypt Private Decrypt Public

asp.netasp.net-mvccencryptionrsa

Here is the problem I am trying to solve. Let's say I was releasing some web software built on ASP.NET MVC and I only wanted the end user to be able to add X users to the system. The software would be hosted on their servers.

I want to include an encrypted file that when the user tries to add a new user, it goes out and reads from the file an encrypted string. When the website decodes it, the clear text will be the number of allowed users.

What is the best/simplest way on my end to encrypt to generate this string on my end then decode it back to clear text in my application? Obviously I want to ensure that the end user cannot be spinning up their own encrypted string and just replace mine. I don't want to worry about having to try and obfuscate my source so that they would not be able to see how I decode the string.

Is it possible to encrypt with a private rsa key, then decrypt it with the public one? I haven't had luck with that in the code below:

        var rsa = new RSACryptoServiceProvider();

        var pubicKey = rsa.ToXmlString(false);
        var privateKey = rsa.ToXmlString(true);

        var test = "this string needs to be encrypted then decrypted";

        var rsa2 = new RSACryptoServiceProvider();
        rsa2.FromXmlString(privateKey);

        var encryptedBytes = rsa2.Encrypt(Encoding.UTF8.GetBytes(test), false);
        var encryptedString = Convert.ToBase64String(encryptedBytes);

        var rsa3 = new RSACryptoServiceProvider();
        rsa3.FromXmlString(pubicKey);

        encryptedBytes = Convert.FromBase64String(encryptedString);

        var decryptedString = Encoding.UTF8.GetString(rsa3.Decrypt(encryptedBytes,                        false));      

Best Answer

You can use a signature strategy, where the private key is used to generate a signature that verifies that your message is authentic.

// Create message and signature on your end
string message = "Here is the license message";

var converter = new ASCIIEncoding();
byte[] plainText = converter.GetBytes(secret);

var rsaWrite = new RSACryptoServiceProvider();
var privateParams = rsaWrite.ExportParameters(true);

// Generate the public key / these can be sent to the user.
var publicParams = rsaWrite.ExportParameters(false);

byte[] signature =
    rsaWrite.SignData(plainText, new SHA1CryptoServiceProvider());

// Verify from the user's side. Note that only the public parameters
// are needed.
var rsaRead = new RSACryptoServiceProvider();
rsaRead.ImportParameters(publicParams);
if (rsaRead.VerifyData(plainText,
                       new SHA1CryptoServiceProvider(),
                       signature))
{
    Console.WriteLine("Verified!");
}
else
{
    Console.WriteLine("NOT verified!");
}

This example was largely copied from Microsoft's site:

And here is web page that explains the concept: