0
votes

Hello Stackoverflow users, I am working on assignment regarding RSA encryption and decryption and have hit a sticky spot.

Using Visual Studio I have created a simple form with 2 textboxes (one for the plain text message and the other to display the encrypted message) and 4 buttons (2 clear buttons to clear corresponding textboxes and an encryption button and decryption button).

public partial class Form1 : Form
{
    //Strings to hold public & private keys
    String publicKey, privateKey; 
    UnicodeEncoding encoder = new UnicodeEncoding();

    public Form1()
    {
        RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
        InitializeComponent();
        privateKey = myRSA.ToXmlString(true);
        publicKey = myRSA.ToXmlString(false);
    }

    private void btnClr1_Click(object sender, EventArgs e)
    {
        txtPlain.Text = "";
        txtPlain.Refresh();
    }

    private void btnClr2_Click(object sender, EventArgs e)
    {
        txtCypher.Text = "";
        txtCypher.Refresh();
    }

    private void btnEncrypt_Click(object sender, EventArgs e)
    {
        var myRSA = new RSACryptoServiceProvider();

        //Set cryptoserviceprovider with the proper key
        myRSA.FromXmlString(publicKey);

        //Encode the data to encrypt as a byte array
        var dataToEncrypt = encoder.GetBytes(txtPlain.Text);

        //Encrypt the byte array
        var encryptedByteArray = myRSA.Encrypt(dataToEncrypt, false).ToArray();

        var length = encryptedByteArray.Count();
        var item = 0;
        var sb = new StringBuilder();

        //Change each byte in the encrypted byte array to text
        foreach(var x in encryptedByteArray)
        {
            item++;
            sb.Append(x);
            if (item < length) sb.Append(",");
        }
        txtCypher.Text = sb.ToString();
    }

    private void btnDecrypt_Click(object sender, EventArgs e)
    {
        var myRSA = new RSACryptoServiceProvider();

       //Split data into an array
        var dataArray = txtCypher.Text.Split(new char[] { ',' });

        //Convert chars to bytes
        byte[] dataByte = new byte[dataArray.Length];

        for(int i = 0; i < dataArray.Length; i++) dataByte[i] = Convert.ToByte(dataArray[i]);

        //Decrypt the byte array
        myRSA.FromXmlString(privateKey);
        var decryptedBytes = myRSA.Decrypt(dataByte, false);

        //place into cypher text box
        txtPlain.Text = encoder.GetString(decryptedBytes);
    }
}

I have no issues with encrypting and decrypting messages (as long as they don't exceed the RSA key size, obviously).

So I am working to modify my program to allow for any size messages to be encrypted and decrypted.

This is the code I have come up with to allow for any size to be encrypted (which seems to work)

private void btnEncrypt_Click(object sender, EventArgs e)
    {
        var myRSA = new RSACryptoServiceProvider();

        //Set cryptoserviceprovider with the proper key
        myRSA.FromXmlString(publicKey);

        //Encode the data to encrypt as a byte array
        var dataToEncrypt = encoder.GetBytes(txtPlain.Text);

        //store dataLength
        int dataLength = dataToEncrypt.Length;

        //Check if dataLength > 128 
        if (dataLength > 128)
        {
            //Divide dataLength by 128 to determine how many cycles will be needed
            double numOfCycles = (dataLength / 117);
            //round up to nearest whole number
            cycles = (int)Math.Ceiling(numOfCycles);


            //for however many cycles
            for (int i = 0; i < cycles; i++)
            {
                var myByteArray = new byte[117];
                for (int j = 0; j < 117; j++)
                {
                    int currentByte = i * 117 + j;
                    myByteArray[j] = dataToEncrypt[currentByte];
                }

                var encryptedByteArray = myRSA.Encrypt(myByteArray, false).ToArray();

                var length = encryptedByteArray.Count();
                var item = 0;

                //Change each byte in the encrypted byte array to text
                foreach (var x in encryptedByteArray)
                {
                    item++;
                    sb.Append(x);
                    if (item < length) sb.Append(",");
                }
                txtCypher.Text = sb.ToString();
            }
        }
        else
        {
            var encryptedByteArray = myRSA.Encrypt(dataToEncrypt, false).ToArray();
            var length = encryptedByteArray.Count();
            var item = 0;
            var sb = new StringBuilder();

            //Change each byte in the encrypted byte array to text
            foreach(var x in encryptedByteArray)
            {
                item++;
                sb.Append(x);
            if (item < length) sb.Append(",");
            }
              txtCypher.Text = sb.ToString();   
            }
    }

And this is the code that I have come up with to handle decryption of any size message (which is what is giving me errors)

 private void btnDecrypt_Click(object sender, EventArgs e)
    {
        var myRSA = new RSACryptoServiceProvider();

       //Split data into an array
        var dataArray = txtCypher.Text.Split(new char[] { ',' });

        int length = dataArray.Count();
        float numOfCycles = (length / 117);
        int cycles = (int)Math.Ceiling(numOfCycles);

        for (int i = 0; i < cycles; i++) 
        {
            byte[] dataByte = new byte[117];
            for(int j = 0; j < 117; j++)
            {
                //Convert chars to bytes
                dataByte[j] = Convert.ToByte(dataArray[ i * 117 + j ]);
            }
            //Decrypt the byte array
            myRSA.FromXmlString(privateKey);
            var decryptedBytes = myRSA.Decrypt(dataByte, false);
            txtPlain.Text += encoder.GetString(decryptedBytes);
        }
    }

The errors that it being thrown is:

`System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll. Additional information: Bad Data.`

from line 133: var decryptedBytes = myRSA.Decrypt(dataByte, false);

Any help/advice would be greatly appreciated! Thanks all!

1
RSA shouldn't be used for more than roughly keysize bits. If you need to encrypt large amounts of data, generate a one-off AES key and encrypt it using RSA. - Luke Joshua Park

1 Answers

0
votes

As Luke Park said, it's generally considered bad practice to try to make RSA a chained algorithm. It's purpose is for secure "key exchange", meaning the encrypted contents are 'supposed' to be symmetric encryption information.

However, if you're determined to go down this road; the problem is that RSA-Encrypt always produces an output whose length is the key size. Your code is assuming 117 bytes in => 117 bytes out; and that's just not the case.

Since RSA-Decrypt expects that you have prepared the data with RSA-Encrypt, it reports "Bad Data" because you haven't given it a valid datagram (a valid one would have length equal to the keysize).