Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#
Tip/Trick

Simple, unbreakable encryption for everyone

Rate me:
Please Sign up or sign in to vote.
4.00/5 (8 votes)
15 Sep 2017CPOL3 min read 19.2K   14   9
Implementation of one-time-pad encryption

Introduction

Encryption is a hot topic in the news currently, with Dutch headlines talking about a possible dragnet to spy on the entire population. It would mean that those currently governing can spy on political opponents.

Background

This tip shows a very simple example implementation of a "one time pad" (see wiki). This is an unbreakable encryption. As long as your key remains private, no government will ever decypher it.

Using the code

Think of a character, any character. Add a random number. If the result is not a valid character, subtract the amount of different characters in your characterset.  The result is your encrypted version, the random number you picked is the key, and the character was the original data. It is that simple.

The reason this is not the default encryption on the internet is the fact that the key becomes as large as the data you are encrypting. Next problem is that you can't send them over the same channel, as that would compromise the key - anyone listening would be able to decode the original.

So this is not very practical for your average webhost. For those who feel they need this level of security, there's an easy alternative. While it may have been impractical to use in the past, it is rather easy to generate a terrabyte worth of random data and put it on a portable harddisk, given to some idiot tourist. Once you need to encrypt a message you use part thereof as your current message. If you both have a copy of the Pad, and the Pad has never been transmitted electronically, you are safe.

You may vary ofcourse; perhaps you feel "safe enough" by protecting the Pad with a PkZip password and sending it using SSL to your own server. I'd always recommend not to transmit it at all; someone can carry a USB stick and deliver it in a day - and you'd instantly have a Pad that is several Gb big.

So, on to the easy code example. First we need code to generate random data that we will use as a Pad.

C#
public static byte[] GeneratePad(int size, int seed)
{
    var random = new Random(Seed: seed);
    var bytesBuffel = new byte[size];

    random.NextBytes(bytesBuffel);

    return bytesBuffel;
}

That's nice and easy, isn't it? Now comes the hard part, implementing an unbreakable encryption algo. The example on wikipedia uses only a subset of printable characters. I was thinking about using the entire byte.

C#
public static byte[] Encrypt(byte[] data, byte[] pad)
{
    var result = new byte[data.Length];
    for (int i = 0; i < data.Length; i++)
    {
        var sum = (int)data[i] + (int)pad[i];
        if (sum > 255)
            sum -= 255;
        result[i] = (byte)sum;
    }
    return result;
}

And the counterpart, which is as complex as the previous example. Seriously, try not to laugh as we look at the method that subtracts the noise we added to our data;

C#
public static byte[] Decrypt(byte[] encrypted, byte[] pad)
{
    var result = new byte[encrypted.Length];
    for (int i = 0; i < encrypted.Length; i++)
    {
        var dif = (int)encrypted[i] - (int)pad[i];
        if (dif < 0)
            dif += 255;
        result[i] = (byte)dif;
    }
    return result;
}

Yes, using those three methods is equally simple.

C#
// Converting text to bytes, assuming unicode.
byte[] originalBytes = Encoding.Unicode.GetBytes(textBoxOriginal.Text);

// generate a pad in memory.
byte[] pad = PadGenerator.GeneratePad(size: originalBytes.Length, seed: 1);

// I'm going to display these bytes in Base64, but one would
// probably save them to a file; this is the Pad (or "key").
textBoxPad.Text = Convert.ToBase64String(inArray: pad);

// We encrypt the bytes by adding our noise.
byte[] encrypted = PadGenerator.Encrypt(originalBytes, pad);

// again, displaying in base64, but you would typically save
// these to a file too; this is your encrypted "file" or message.
textBoxEncrypted.Text = Convert.ToBase64String(inArray: encrypted);

byte[] encryptedFromBase64 = Convert.FromBase64String(textBoxEncrypted.Text);

// decrypting the encoded message using the key made up of noise.
byte[] decrypted = PadGenerator.Decrypt(encryptedFromBase64, pad);

// displaying the original unencrypted message.
textBoxDecrypted.Text = Encoding.Unicode.GetString(decrypted);

That's it, as they say.

Points of Interest

This works best for IM/Email messages, in places where you can transmit your key physically and protect it. With the current number of bytes you can store for a dollar, there's no reason not to generate a pad. Once both locations share their secret key (and do NOT reuse it) one can talk in private.

I've decided to share the interesting part of the project, instead of an entire solution that can be run directly. The latter would be more popular, but by sharing the idea and not the project there will be multiple implementations. Each with its own weird quircks.

If you do, then forget about the base64-conversions in this example; they're only there for me to make it easy with copy/pasting and testing. It's a nice way of displaying data that may contain non-printable characters. If you want to be really fancy, you use a hex-viewer to show those bytes :)

History

  • September 15th, 2017 - initial draft.
<!-- "X-Clacks-Overhead" content="GNU Terry Pratchett" -->

License

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


Written By
Software Developer Currently none.
Netherlands Netherlands
I'm a Delphi-convert, mostly into WinForms and C#. My first article is from 2001, extending the Delphi-debugger, which is still visible on the WayBackMachine[^] and even available in Russian[^] Smile | :)

Comments and Discussions

 
QuestionUsefulness? Pin
djmarcus28-Sep-17 13:25
djmarcus28-Sep-17 13:25 
AnswerRe: Usefulness? Pin
Eddy Vluggen2-Dec-17 5:11
professionalEddy Vluggen2-Dec-17 5:11 
GeneralRe: Usefulness? Pin
Wandee Thaweetham10-Apr-22 18:03
Wandee Thaweetham10-Apr-22 18:03 
Question[My vote of 2] Perfomrance issues Pin
Member 1027172721-Sep-17 21:08
Member 1027172721-Sep-17 21:08 
AnswerRe: [My vote of 2] Perfomrance issues Pin
Eddy Vluggen23-Sep-17 8:11
professionalEddy Vluggen23-Sep-17 8:11 
SuggestionSytem.Random is not safe for cryptography Pin
webmaster44217-Sep-17 2:22
webmaster44217-Sep-17 2:22 
The System.Random class is not safe enough for cryprographic purposes. You should use the RNGCryptoServiceProvider class: RNGCryptoServiceProvider Class (System.Security.Cryptography)[^]
GeneralRe: Sytem.Random is not safe for cryptography Pin
Eddy Vluggen17-Sep-17 3:49
professionalEddy Vluggen17-Sep-17 3:49 
QuestionMy vote of 5 Pin
Bohdan Stupak16-Sep-17 2:20
professionalBohdan Stupak16-Sep-17 2:20 
AnswerRe: My vote of 5 Pin
Eddy Vluggen16-Sep-17 5:59
professionalEddy Vluggen16-Sep-17 5:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.