Introduction
This (my first) article is a simple demonstration of public key cryptography and a character substitution encryption method. Additionally the GUI demonstrates how to select and color text in a RichTextBox, threads, and referencing GUI controls from a thread they were not created on.
The techniques employed in the code are NOT intended to be used in any production environment. This is learning tool ONLY.
Background
This was a project assignment for a course I took on Operating Systems - Security.
I made use of code I found on Wikipedia (https://en.wikipedia.org/wiki/RSA_(cryptosystem)) and the CodeProject site. Visual Studio 2015 was used to build the project.
Using the code
To use the Demo app you can open a plain text file or enter your own plain text in the input box. If you select 'Table' instead of 'Public Key' be aware that only a subset of non-alphanumeric characters will be encrypted. If you want handle a larger set of special characters, just add them to either the 'unencrypted_char_table' or the 'encryption_table'.
Select 'Encryp' or 'Decrypt' as appropriate. Click 'Next' to single step through each character. Or click 'Run' to watch the process, 'Stop' to stop running. Click 'Reset' to start from the beginning.
If you want to save the encrypted Output to a file, click the 'Save As' button. You can reload the saved file for decryption later in the current session. Be aware the a new set of keys are generated each time the program is run.
'1st Prime' and '2nd Prime' selections are the two distinct "random" prime numbers used for key generation. The values are deliberately kept small so that a simple hand calculator can be used to reproduce the results. In the real world public key encryption uses very large prime numbers.
Encryption is simple and commented.
private string Encrypt(string _inChar)
{
string _out = "\n";
if (radioButton_public_key.Checked)
{
input_p = _inChar[0];
BigInteger _mod = BigInteger.ModPow(input_p, public_key_e, public_key_n);
return _mod.ToString("00000");
}
if (unencoded_digits)
{
if (digits_table.Contains(_inChar))
{
_out = _inChar;
}
else
{
unencoded_digits = false;
_out = "^^";
if (unencrypted_char_table.Contains(_inChar))
{
_out += _inChar;
}
else if (encryption_table.ContainsKey(_inChar.ToString()))
{
_out += encryption_table[_inChar].ToString();
}
}
}
else
{
if (digits_table.Contains(_inChar))
{
unencoded_digits = true;
_out = "^^" + _inChar;
}
else if (unencrypted_char_table.Contains(_inChar))
{
_out = _inChar;
}
else if (encryption_table.ContainsKey(_inChar.ToString()))
{
_out = encryption_table[_inChar].ToString();
}
}
if (unencoded_digits)
{
string _inText = GetControlProperty(richTextBox_input, "Text").ToString();
if (inputCursor + _inChar.Length >= _inText.Length)
{
_out += "^^";
}
}
return _out;
}
Decryption is similarly commented.
private string Decrypt(ref string _inChar)
{
string _out = string.Empty;
if (radioButton_public_key.Checked)
{
if (_inChar == "\n")
return _inChar;
input_p = BigInteger.Parse(_inChar);
char _mod = (char)BigInteger.ModPow(input_p, private_key, public_key_n);
return _mod.ToString();
}
if (digits_table.Contains(_inChar[0]))
{
if (unencoded_digits)
{
_inChar = _inChar.Substring(0, 1);
return _inChar;
}
else
{
int _cipherNumber;
if (int.TryParse(_inChar.Substring(0, 2), out _cipherNumber))
{
if (encryption_table.ContainsValue(_cipherNumber))
{
_inChar = _inChar.Substring(0, 2);
return encryption_table.FirstOrDefault(x => x.Value == _cipherNumber).Key.ToString();
}
}
}
}
if (unencrypted_char_table.Contains(_inChar[0]))
{
_inChar = _inChar.Substring(0, 1);
return _inChar;
}
else if (_inChar[0] == '^')
{
if (_inChar.Substring(0, 2) == "^^")
{
unencoded_digits = !unencoded_digits;
return _inChar.Substring(2, 1);
}
}
_inChar = _inChar.Substring(0, 1);
return _inChar;
}
History
Version 1.0