A Scytale Algorithm in CSharp

I wrote about a simple reciprocal substitution cipher before and today I will write about a simple transposition cipher. In a substitution cipher, the letters stay in their positions, but they change their identities. They may be changed to another letter or symbol. The ROT-13 algorithm (see previous link) and the Caesar cipher are two examples of a substitution cipher.

In a transposition cipher, the letters keep their identities, but their positions are switched (or transposed). An example of a transposition cipher is the Scytale (rhymes with Italy) tool used in ancient Greece to encrypt messages sent to troops and officers during battle.

The Scytale is a rod in which the sender wraps a strip of parchment paper and writes the message on that strip. The messenger then carries the message to the receiver, who must have another Scytale of the same diameter of the one used to create the encrypted message. The receiver wraps the strip on his Scytale and is able to read the message.

Scytale

The Scytale points to an interesting concept in cryptography: it's really difficult to keep an algorithm secret. The security of a cipher should not be dependent on keeping the method of encryption a secret. In the case of Scytale, the method of encryption is the rod used, but there is another aspect: the diameter of the rod is also important. The diameter is the key of the algorithm.

The Implementation

The implementation of the algorithm is really simple and there are many methods one can use to achieve the same goal. The approach I used breaks down the plain text into a list of characters and then splits this list into chunks of size equal to the key. The next step is to read the first character of each chunk and then the second character of each chunk and so on until all characters are read. The algorithm look like this in CSharp:

public string Encrypt(string plaintext, int key) {
    var chars = plaintext.ToList();
    var chunks = (int)Math.Ceiling(((double)chars.Count() / (double)key));
    var inters = new List<list>();
    int i = 0, j = 0;

    while (i = inters[l].Count())
                buff.Append("+");
            else
                buff.Append(inters[l][k]);
            l++;
        }
        k++;
    }

    return buff.ToString();
}

Note that we have to pad the last chunk if the chunk size is not equal to the key size. Also not that this is not a reciprocal algorithm, as is the case with the ROT-13 implementation. In order to decrypt a message to plain text you need to run it through another function that does things backwards. Note how this code is very similar to the encryption code, but things are down in a different order:

public string Decrypt(string ciphertext, int key) {
    var chars = ciphertext.ToList();
    var chunks = (int)Math.Ceiling(((double)chars.Count() / (double)key));
    var inters = new List<list>();
    int i = 0, j = 0;

    while (i < key) {
        inters.Add(chars.Skip(j).Take(chunks).ToList());
        ++i; j += chunks;
    }

    StringBuilder buff = new StringBuilder();
    int k = 0;

    while (k < chunks) {
        int l = 0;
        while (l < inters.Count()) {
            buff.Append(inters[l][k]);
            l++;
        }
        k++;
    }

    return buff.ToString();
}

Using the Algorithm

To use the Scytale cipher algorithm, you simply have to call the Encrypt and Decrypt functions of the Scytale class and send it a message to encrypt or decrypt along with the key size. In the example code below the Main function uses command line arguments passed in:

static void Main(string[] args) {
    Scytale scytale = new Scytale();

    string msg = args[0]; //"HELPMEIAMUNDERATTACK";
    int key = Int32.Parse(args[1]);

    string cipher = scytale.Encrypt(msg, key);
    string plain = scytale.Decrypt(cipher, key); ;

    Console.WriteLine("Message: " + msg);
    Console.WriteLine("Cipher:  " + cipher);
    Console.WriteLine("Plain:   " + plain);

    Console.ReadKey();
}

You can also call the scytale.exe program like this:

d:\> scytale.exe "HELPMEIAMUNDERATTACK" 5

The output should be the following:

Message: HELPMEIAMUNDERATTACK
Cipher:  HENTEIDTLAEAPMRCMUAK
Plain:   HELPMEIAMUNDERATTACK

Comments

Comments powered by Disqus