65.9K
CodeProject is changing. Read more.
Home

Simple Cryptography Demo

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.24/5 (8 votes)

Jun 29, 2016

CPOL

2 min read

viewsIcon

18381

downloadIcon

545

A simple demonstration of public key cryptography and a character substitution encryption method.

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.

        //-----------------------------------------------------------------------------------
        // Encrypt a single character
        //-----------------------------------------------------------------------------------
        private string Encrypt(string _inChar)
        {
            string _out = "\n";

            // public key encryption?
            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");
            }

            // currently encrypting digits?
            if (unencoded_digits)
            {
                // we are currently processing unencrypted digits
                // is the input character a digit?
                if (digits_table.Contains(_inChar))
                {
                    // yes, return the digit character
                    _out = _inChar;
                }
                else
                {
                    // no, the input character is not a digit - we have reached the end of the digit sequence
                    unencoded_digits = false;
                    // end the unencoded digits sequence
                    _out = "^^";
                    // is this a normally unencrypted character?
                    if (unencrypted_char_table.Contains(_inChar))
                    {
                        // yes, add the character to the output
                        _out += _inChar;
                    }
                    // it's not a normally unencrypted character - should this character be encrypted?
                    else if (encryption_table.ContainsKey(_inChar.ToString()))
                    {
                        // yes, lookup cipher character in the dictionary
                        _out += encryption_table[_inChar].ToString();
                    }
                }
            }
            else  // not currently encrypting digits
            {
                // is the current character a digit?
                if (digits_table.Contains(_inChar))
                {
                    // begin the unencoded digit sequence
                    unencoded_digits = true;
                    _out = "^^" + _inChar;
                }
                // is this a normally unencrypted character?
                else if (unencrypted_char_table.Contains(_inChar))
                {
                    _out = _inChar;
                }
                // should this character be encrypted?
                else if (encryption_table.ContainsKey(_inChar.ToString()))
                {
                    // lookup cipher character(s) in the dictionary
                    _out = encryption_table[_inChar].ToString();
                }
            }
            if (unencoded_digits)
            {
                // is the digit the last character in the input?
                string _inText = GetControlProperty(richTextBox_input, "Text").ToString();
                // peek into the future
                if (inputCursor + _inChar.Length >= _inText.Length)
                {
                    // yes, it is the last character
                    _out += "^^";
                }
            }
            return _out;
        }

Decryption is similarly commented.

        //-----------------------------------------------------------------------------------
        // Decrypt a single character or a pair of characters
        //-----------------------------------------------------------------------------------
        private string Decrypt(ref string _inChar)
        {
            string _out = string.Empty;

            // public key encryption?
            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();
            }

            // is the input character a digit 0 - 9?
            if (digits_table.Contains(_inChar[0]))
            {
                // are we processing unencoded digits?
                if (unencoded_digits)
                {
                    // yes, unencoded digits
                    _inChar = _inChar.Substring(0, 1);
                    return _inChar;
                }
                else
                {
                    // no, these are cipher digits
                    // get two characters
                    // parse the ASCII number
                    int _cipherNumber;
                    if (int.TryParse(_inChar.Substring(0, 2), out _cipherNumber))
                    {
                        // reverse lookup in dictionary
                        if (encryption_table.ContainsValue(_cipherNumber))
                        {
                            _inChar = _inChar.Substring(0, 2);
                            return encryption_table.FirstOrDefault(x => x.Value == _cipherNumber).Key.ToString();
                        }
                    }
                }
            }
            // is this a normally unencrypted character?
            if (unencrypted_char_table.Contains(_inChar[0]))
            {
                // unencoded character
                _inChar = _inChar.Substring(0, 1);
                return _inChar;
            }
            // is this the enclosure for unencrypted digits?
            else if (_inChar[0] == '^')
            {
                // see if there is another carat
                if (_inChar.Substring(0, 2) == "^^")
                {
                    // flip the unencoded state
                    unencoded_digits = !unencoded_digits;
                    // discard the first two carats, return the third character
                    // skip over the first two carats
                    return _inChar.Substring(2, 1);
                }
            }

            _inChar = _inChar.Substring(0, 1);
            return _inChar;
        }
    

 

History

Version 1.0