Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security / cryptography

Simple Cryptography Demo

4.24/5 (8 votes)
29 Jun 2016CPOL2 min read 18.4K   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.

Image 1

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.

C#
//-----------------------------------------------------------------------------------
// 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.

C#
//-----------------------------------------------------------------------------------
// 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)