Welcome to the first entry in my libcodebusters series! In these, I’ll explain the various methods in my libcodebusters code and how they work.

libcodebusters is basically a bunch of methods that allow you to encode and decode text with a variety of ciphers. I’ve made Java and Python versions of the code.

The first method I’ll be explaining is that for Aristocrat encoding. The Aristocrat is a very well-known monoalphabetic substitution cipher with a few important characteristics:

  • Each letter maps to only one other in the alphabet. “E” can’t map to both “I” and “O”.
  • A letter cannot map to itself.
  • There doesn’t have to be a pattern in how the letters map.

With all that said, let’s look at how libcodebusters handles Aristocrat encodes. The first step is just to create an empty string:

Just an empty string
  • java
  • python
1
2
3
public static String aristocrat(String plaintext) {
    String ciphertext = "";
    

After that, let’s make a new array (or list in the Python version) called map. map is the result of the Utils.alphMap function (Utils being where I store all my repeated helper methods), which is kind of the secret to making this whole thing work. Here’s the code for alphMap:

alphMap - randomly map letters
  • java
  • python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static int[] alphMap() {
    boolean[] used = new boolean[26];
    for(boolean item : used) {
        item = false;
    }
    int[] map = new int[26];
    for(int i = 0; i < 26; i++) {
        int newval;
        do {
            newval = (int)(Math.random() * 26);
        }
        while(newval == i || used[newval]);
        used[newval] = true;
        map[i] = newval;
    }
    return map;
}
    

There are two arrays/lists in alphMapused and map. The way this works is that used is made as a 26-item set of falses. For each plaintext letter A-Z (0-25 numerically), a new value (appropriately named newval) is generated. newval’s value keeps randomly changing while newval == i (i being the iterator–i.e. whenever the ciphertext letter equals the plaintext letter) or used[newval] is true (i.e. whenever the ciphertext letter is already mapped to a plaintext letter). When a satisfactory value for newval is found, used[newval] is set as true to indicate that the ciphertext letter is now taken, and map[i]’s value becomes newval (in map, the indices represent the plaintext letters, and the values represent the ciphertext letters). After map is filled up, we return it as the output of alphMap.

Following this, we’ll make the plaintext uppercase (so that we don’t have to deal with two sets of ASCII codes, and also because case sensitivity doesn’t usually matter with ciphers), then use this handy loop to switch all the characters:

Actually encoding the text, featuring for loops
  • java
  • python
1
2
3
4
5
6
7
8
for(int i = 0; i < plaintext.length(); i++) {
    int ascii = plaintext.charAt(i);
    if(Utils.isLetter(ascii)) {
        ciphertext += (char)(map[ascii - 65] + 65);
    }
    else ciphertext += (char)(plaintext.charAt(i));
}
    

The way this works is that, for each character in plaintext, the program gets the character’s ASCII value and then uses Utils.isLetter to check if it’s a mappable letter. isLetter checks if a value is between 65 and 90, inclusive (the ASCII codes for “A” through “Z”). If the character is a letter, the code subtracts 65 from its ASCII value (giving a number between 0 and 25, inclusive), gets the mapped value (which, remember, is an integer, not a character), and adds 65 to get the newly encoded letter’s ASCII value. The character is then added to the end of the string we made at the very beginning. If the plaintext character isn’t a letter, the code just skips to the last part and adds the character. After this, the ciphertext string is returned. Congratulations, you’ve encoded text using the Aristocrat cipher!

Here’s how the full method looks:

Full Aristocrat encode!
  • java
  • python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static String aristocrat(String plaintext) {
    String ciphertext = "";
    int[] map = Utils.alphMap();
    plaintext = plaintext.toUpperCase();
    for(int i = 0; i < plaintext.length(); i++) {
        int ascii = plaintext.charAt(i);
        if(Utils.isLetter(ascii)) {
            ciphertext += (char)(map[ascii - 65] + 65);
        }
        else ciphertext += (char)(plaintext.charAt(i));
    }
    return ciphertext;
}