C# - Encrypting and Decrypting Data using RSA

14,784

Solution 1

Don't treat encrypted data as a string. Encryption algorithms work on binary data, and produce binary data, which cannot be interpreted as a string. It's naive to think that UTF-8 or any other encoding will be able to interpret any given chunk of binary data as a valid character string.

In your case, if you need to output encrypted data to the console for debugging purposes, go ahead with byte[] and dump it in hexadecimal, like this:

for (int i = 0; i < data.Length; i++)
{
    Console.Write(data[i].ToString("X2"));
    Console.Write(" ");
    if ((i+1) % 16 == 0) Console.WriteLine();
}

Solution 2

you can use base64 Format to convert type of variable (encryptedText) parameter by replace the functions

public string Encrypt(string plainText, X509Certificate2 cert)
{
    RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
    byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
    byte[] encryptedBytes = publicKey.Encrypt(plainBytes, false);
    string encryptedText = Convert.ToBase64String(encryptedBytes);
    return encryptedText;
}

public string Decrypt(string encryptedText, X509Certificate2 cert)
{
    RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
    byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
    byte[] decryptedBytes = privateKey.Decrypt(encryptedBytes, false);
    string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
    return decryptedText;
}
Share:
14,784

Related videos on Youtube

Matthew
Author by

Matthew

Updated on September 15, 2022

Comments

  • Matthew
    Matthew over 1 year

    I have the following code in C#:

    Main Class

    X509Certificate2 cert = new X509Certificate2("C:/test.pfx", "hello", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
    
                Encryption enc = new Encryption();
                string encrypted = enc.Encrypt("hello there", cert);
                string decrypted = enc.Decrypt(encrypted, cert);
                Console.WriteLine("Encrypted Text: " + encrypted);
                Console.WriteLine("Decrypted Text: " + decrypted);
    

    Encryption Class

    public string Encrypt(string plainText, X509Certificate2 cert)
    {
        RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key;
        byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
        byte[] encryptedBytes = publicKey.Encrypt(plainBytes, false);
        string encryptedText = encryptedBytes.ToString();
        return encryptedText;
    }
    
    public string Decrypt(string encryptedText, X509Certificate2 cert)
    {
        RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
        byte[] encryptedBytes = Encoding.UTF8.GetBytes(encryptedText);
        byte[] decryptedBytes = privateKey.Decrypt(encryptedBytes, false);
        string decryptedText = decryptedBytes.ToString();
        return decryptedText;
    }
    

    As you can see, in the main class I am importing a certificate. Then I am creating an instance of the Encryption class. Then I pass plaintext to the Encrypt method along with the certificate in order to get the encrypted text. Afterwards, I pass the encrypted text to the Decrypt method to get the plaintext back.

    My problem is that the result of printing the encrypted text is System.[]Byte (if I comment out the decryption call). If I do not comment out the decryption call, I get a Cryptographic Exception: Bad Data in the decryption method.

    I guess that the encryptedBytes array is not being converted correctly to string. Furthermore, I am not sure if I am forming the RSAEncryptionProvider correctly. How can I solve this please?

    Update

    I solved one issue. When converting from byte array to string, I had to use Encoding.UTF8.GetString(EncryptedBytes). The problem now is that the decrypt method is giving me another cryptographic exception (he data to be decrypted exceeds the maximum for this modulus of 128 bytes).

    Does anybody know why this is happening and how to solve it?

    • Eugene Mayevski 'Callback
      Eugene Mayevski 'Callback about 11 years
      Encryption is always done on binary data (although it might look as a string for you) and always produces binary data as output. Why are you expecting any strings?
    • Matthew
      Matthew about 11 years
      @OndrejTucny Thank you for your suggestion :)
  • Legends
    Legends about 8 years
    But how do you use RSA encryption if you want to pass the encrypted byte[] data from Server A (Windows) to another server B running on Linux?
  • Ondrej Tucny
    Ondrej Tucny about 8 years
    @Legends The operating system you use is irrelevant in respect to how encryption works.
  • Legends
    Legends about 8 years
    What I wanted to say is, that Matthew said this in a comment: >>I want to display the text on the screen to see if it really works<< So this was his intention, to display the text to see if his enc/dec functions work: But you said binary data cannot be interpreted as string. And this is wrong, or did you mean something else? Like this: var cert = getC(); RSACryptoServiceProvider rsa= (RSACryptoServiceProvider)cert.PublicKey.Key; byte[] cipherData = rsa.Encrypt(Encoding.UTF8.GetBytes(plainData), _onlyValidCerts); return Convert.ToBase64String(cipherData);
  • Ondrej Tucny
    Ondrej Tucny about 8 years
    @Legends The answer is (a) three years old, (b) accepted. I'm not getting what you are trying to say here. There's like a thousand methods to dump a chunk of binary data to the console. The one in my answer is correct, worked and was accepted by the OP. Feel free to use ToBase64String should you prefer that kind of output.