Foursquare Cipher


#1

So I thought Mdog’s Java Playfair implementation was pretty cool, so I wrote my own implementation of a similar cipher named Foursquare.

http://en.wikipedia.org/wiki/Four-square_cipher

The four-square cipher uses four 5 by 5 matrices arranged in a square. Each of the 5 by 5 matrices contains the letters of the alphabet (usually omitting "Q" or putting both "I" and "J" in the same location to reduce the alphabet to fit). In general, the upper-left and lower-right matrices are the "plaintext squares" and each contain a standard alphabet. The upper-right and lower-left squares are the "ciphertext squares" and contain a mixed alphabetic sequence. To generate the ciphertext squares, one would first fill in the spaces in the matrix with the letters of a keyword or phrase (dropping any duplicate letters), then fill the remaining spaces with the rest of the letters of the alphabet in order (again omitting "Q" to reduce the alphabet to fit). The key can be written in the top rows of the table, from left to right, or in some other pattern, such as a spiral beginning in the upper-left-hand corner and ending in the center. The keyword together with the conventions for filling in the 5 by 5 table constitute the cipher key. The four-square algorithm allows for two separate keys, one for each of the two ciphertext matrices.

If you’re interested on how the ciphertext is generated, go on the article, there is alot of information about the cipher on there.

import java.util.ArrayList;
import java.util.List;

/**
 * Java implementation of the Foursquare cipher.
 * Made by Ollie123 with portions taken from m.dog311's Playfair implementation.
 * @author Ollie
 */
public class Foursquare {

    /**
     * Alphabet template, excluding Q.
     */
    private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPRSTUVWXYZ".toCharArray();
    /**
     * Alphabet square.
     */
    private static final char[][] ALPHABET_SQUARE = new char[5][5];

    /**
     * Static block to populate the Alphabet Square.
     */
    static {
        int x = 0, y = 0;
        for (char c : ALPHABET) {
            ALPHABET_SQUARE[x][y] = c;
            x++;
            if (x == 5) {
                x = 0;
                y++;
            }
        }
    }

    /**
     * Cleans a plaintext or keyword ready for use in the Foursquare cipher.
     * @param input the text to clean
     * @return the clean text
     */
    private static String clean(String input) {
        input = input.trim().replace(" ", "").replace("Q", "").toUpperCase();
        StringBuilder clean = new StringBuilder();
        for (char c : input.toCharArray()) {
            if (Character.getType(c) == Character.UPPERCASE_LETTER) {
                clean.append(c);
            }
        }
        return clean.toString();
    }

    /**
     * Generates a 5*5 key table for the specified keyword.
     * @param keyword the keyword from which to generate the table
     * @return the newly generated key table
     */
    private static char[][] generateKeyTable(String keyword) {
        keyword = clean(keyword);
        char[][] keyTable = new char[5][5];
        List<Character> used = new ArrayList<Character>();
        int x = 0, y = 0;
        for (char c : keyword.toCharArray()) {
            if (!used.contains(c)) {
                keyTable[x][y] = c;
                used.add(c);
                x++;
                if (x == 5) {
                    x = 0;
                    y++;
                    if (y == 5) {
                        return keyTable;
                    }
                }
            }
        }
        for (char c : ALPHABET) {
            if (!used.contains(c)) {
                keyTable[x][y] = c;
                x++;
                if (x == 5) {
                    x = 0;
                    y++;
                    if (y == 5) {
                        return keyTable;
                    }
                }
            }
        }
        return keyTable;
    }

    /**
     * Splits a string into two-letter strings (digraphs). Portions courtesy m.dog311.
     * @param plaintext the string to split
     * @return an array of two-letter strings
     */
    private static String[] split(String plaintext) {
        if (plaintext.length() % 2 != 0) {
            plaintext = plaintext + "X";
        }
        String[] pairs = new String[plaintext.length() / 2];
        int count = 0;
        for (int i = 0; i < (plaintext.length() / 2); i++) {
            pairs[i] = plaintext.substring(count, count + 2);
            count = count + 2;
        }
        return pairs;
    }

    /**
     * Encrypts a plaintext with Foursquare using the two specified keywords.
     * @param plaintext the text to encrypt
     * @param keyword1 the first keyword to use
     * @param keyword2 the second keyword to use
     * @return the ciphertext
     */
    public static String encrypt(String plaintext, String keyword1, String keyword2) {
        plaintext = clean(plaintext);
        String[] pairs = split(plaintext);
        char[][] keytable1 = generateKeyTable(keyword1);
        char[][] keytable2 = generateKeyTable(keyword2);
        char first, second;
        int xFirst = 0, yFirst = 0, xSecond = 0, ySecond = 0;
        StringBuilder ciphertext = new StringBuilder();
        for (String s : pairs) {
            first = s.charAt(0);
            second = s.charAt(1);
            for (int y = 0; y < 5; y++) {
                for (int x = 0; x < 5; x++) {
                    if (ALPHABET_SQUARE[x][y] == first) {
                        xFirst = x;
                        yFirst = y;
                    } else if (ALPHABET_SQUARE[x][y] == second) {
                        xSecond = x;
                        ySecond = y;
                    }
                }
            }
            ciphertext.append(keytable1[xSecond][yFirst]).append(keytable2[xFirst][ySecond]);
        }
        return ciphertext.toString();
    }

    /**
     * Decrypts a Foursquare-encrypted ciphertext using the two specified keywords.
     * @param ciphertext the text to decrypt
     * @param keyword1 the first keyword to use
     * @param keyword2 the second keyword to use
     * @return the plaintext
     */
    public static String decrypt(String ciphertext, String keyword1, String keyword2) {
        String[] pairs = split(ciphertext);
        char[][] keytable1 = generateKeyTable(keyword1);
        char[][] keytable2 = generateKeyTable(keyword2);
        char first, second;
        int xFirst = 0, yFirst = 0, xSecond = 0, ySecond = 0;
        StringBuilder plaintext = new StringBuilder();
        for (String s : pairs) {
            first = s.charAt(0);
            second = s.charAt(1);
            for (int y = 0; y < 5; y++) {
                for (int x = 0; x < 5; x++) {
                    if (keytable1[x][y] == first) {
                        xFirst = x;
                        yFirst = y;
                    } else if (keytable2[x][y] == second) {
                        xSecond = x;
                        ySecond = y;
                    }
                }
            }
            plaintext.append(ALPHABET_SQUARE[xSecond][yFirst]).append(ALPHABET_SQUARE[xFirst][ySecond]);
        }
        return plaintext.toString();
    }

    public static void main(String[] args) {
        try {
            if(args[0].equalsIgnoreCase("-d")) {
                System.out.println(decrypt(args[1], args[2], args[3]));
            } else {
                System.out.println(encrypt(args[0], args[1], args[2]));
            }
        } catch (ArrayIndexOutOfBoundsException ex) {
            System.out.println("USAGE: java Foursquare [-d] <plaintext|ciphertext> <first keyword> <second keyword>");
        }
    }
}

#2

[quote=“ollie123, post:1, topic:409572”]So I thought Mdog’s Java Playfair implementation was pretty cool, so I wrote my own implementation of a similar cipher named Foursquare.

http://en.wikipedia.org/wiki/Four-square_cipher

[quote]The four-square cipher uses four 5 by 5 matrices arranged in a square. Each of the 5 by 5 matrices contains the letters of the alphabet (usually omitting “Q” or putting both “I” and “J” in the same location to reduce the alphabet to fit). In general, the upper-left and lower-right matrices are the “plaintext squares” and each contain a standard alphabet. The upper-right and lower-left squares are the “ciphertext squares” and contain a mixed alphabetic sequence.
To generate the ciphertext squares, one would first fill in the spaces in the matrix with the letters of a keyword or phrase (dropping any duplicate letters), then fill the remaining spaces with the rest of the letters of the alphabet in order (again omitting “Q” to reduce the alphabet to fit). The key can be written in the top rows of the table, from left to right, or in some other pattern, such as a spiral beginning in the upper-left-hand corner and ending in the center. The keyword together with the conventions for filling in the 5 by 5 table constitute the cipher key. The four-square algorithm allows for two separate keys, one for each of the two ciphertext matrices.[/quote]

If you’re interested on how the ciphertext is generated, go on the article, there is alot of information about the cipher on there.

[code=java]
import java.util.ArrayList;
import java.util.List;

/**

  • Java implementation of the Foursquare cipher.

  • Made by Ollie123 with portions taken from m.dog311’s Playfair implementation.

  • @author Ollie
    */
    public class Foursquare {

    /**

    • Alphabet template, excluding Q.
      /
      private static final char[] ALPHABET = “ABCDEFGHIJKLMNOPRSTUVWXYZ”.toCharArray();
      /
      *
    • Alphabet square.
      */
      private static final char[][] ALPHABET_SQUARE = new char[5][5];

    /**

    • Static block to populate the Alphabet Square.
      */
      static {
      int x = 0, y = 0;
      for (char c : ALPHABET) {
      ALPHABET_SQUARE[x][y] = c;
      x++;
      if (x == 5) {
      x = 0;
      y++;
      }
      }
      }

    /**

    • Cleans a plaintext or keyword ready for use in the Foursquare cipher.
    • @param input the text to clean
    • @return the clean text
      */
      private static String clean(String input) {
      input = input.trim().replace(" ", “”).replace(“Q”, “”).toUpperCase();
      StringBuilder clean = new StringBuilder();
      for (char c : input.toCharArray()) {
      if (Character.getType© == Character.UPPERCASE_LETTER) {
      clean.append©;
      }
      }
      return clean.toString();
      }

    /**

    • Generates a 5*5 key table for the specified keyword.
    • @param keyword the keyword from which to generate the table
    • @return the newly generated key table
      */
      private static char[][] generateKeyTable(String keyword) {
      keyword = clean(keyword);
      char[][] keyTable = new char[5][5];
      List used = new ArrayList();
      int x = 0, y = 0;
      for (char c : keyword.toCharArray()) {
      if (!used.contains©) {
      keyTable[x][y] = c;
      used.add©;
      x++;
      if (x == 5) {
      x = 0;
      y++;
      if (y == 5) {
      return keyTable;
      }
      }
      }
      }
      for (char c : ALPHABET) {
      if (!used.contains©) {
      keyTable[x][y] = c;
      x++;
      if (x == 5) {
      x = 0;
      y++;
      if (y == 5) {
      return keyTable;
      }
      }
      }
      }
      return keyTable;
      }

    /**

    • Splits a string into two-letter strings (digraphs). Portions courtesy m.dog311.
    • @param plaintext the string to split
    • @return an array of two-letter strings
      */
      private static String[] split(String plaintext) {
      if (plaintext.length() % 2 != 0) {
      plaintext = plaintext + “X”;
      }
      String[] pairs = new String[plaintext.length() / 2];
      int count = 0;
      for (int i = 0; i < (plaintext.length() / 2); i++) {
      pairs[i] = plaintext.substring(count, count + 2);
      count = count + 2;
      }
      return pairs;
      }

    /**

    • Encrypts a plaintext with Foursquare using the two specified keywords.
    • @param plaintext the text to encrypt
    • @param keyword1 the first keyword to use
    • @param keyword2 the second keyword to use
    • @return the ciphertext
      */
      public static String encrypt(String plaintext, String keyword1, String keyword2) {
      plaintext = clean(plaintext);
      String[] pairs = split(plaintext);
      char[][] keytable1 = generateKeyTable(keyword1);
      char[][] keytable2 = generateKeyTable(keyword2);
      char first, second;
      int xFirst = 0, yFirst = 0, xSecond = 0, ySecond = 0;
      StringBuilder ciphertext = new StringBuilder();
      for (String s : pairs) {
      first = s.charAt(0);
      second = s.charAt(1);
      for (int y = 0; y < 5; y++) {
      for (int x = 0; x < 5; x++) {
      if (ALPHABET_SQUARE[x][y] == first) {
      xFirst = x;
      yFirst = y;
      } else if (ALPHABET_SQUARE[x][y] == second) {
      xSecond = x;
      ySecond = y;
      }
      }
      }
      ciphertext.append(keytable1[xSecond][yFirst]).append(keytable2[xFirst][ySecond]);
      }
      return ciphertext.toString();
      }

    /**

    • Decrypts a Foursquare-encrypted ciphertext using the two specified keywords.
    • @param ciphertext the text to decrypt
    • @param keyword1 the first keyword to use
    • @param keyword2 the second keyword to use
    • @return the plaintext
      */
      public static String decrypt(String ciphertext, String keyword1, String keyword2) {
      String[] pairs = split(ciphertext);
      char[][] keytable1 = generateKeyTable(keyword1);
      char[][] keytable2 = generateKeyTable(keyword2);
      char first, second;
      int xFirst = 0, yFirst = 0, xSecond = 0, ySecond = 0;
      StringBuilder plaintext = new StringBuilder();
      for (String s : pairs) {
      first = s.charAt(0);
      second = s.charAt(1);
      for (int y = 0; y < 5; y++) {
      for (int x = 0; x < 5; x++) {
      if (keytable1[x][y] == first) {
      xFirst = x;
      yFirst = y;
      } else if (keytable2[x][y] == second) {
      xSecond = x;
      ySecond = y;
      }
      }
      }
      plaintext.append(ALPHABET_SQUARE[xSecond][yFirst]).append(ALPHABET_SQUARE[xFirst][ySecond]);
      }
      return plaintext.toString();
      }

    public static void main(String[] args) {
    try {
    if(args[0].equalsIgnoreCase("-d")) {
    System.out.println(decrypt(args[1], args[2], args[3]));
    } else {
    System.out.println(encrypt(args[0], args[1], args[2]));
    }
    } catch (ArrayIndexOutOfBoundsException ex) {
    System.out.println("USAGE: java Foursquare [-d] <plaintext|ciphertext> ");
    }
    }
    }
    [/code][/quote]

You should try some numeric ciphers.


#3

I might try and implement the Nihilist cipher next :P.


#4

[quote=“ollie123, post:3, topic:409572”][quote author=sinisoul link=topic=510852.msg3707127#msg3707127 date=1313106718]
You should try some numeric ciphers.
[/quote]

I might try and implement the Nihilist cipher next :P.[/quote]

Not what I meant, http://en.wikipedia.org/wiki/Feistel_cipher


#5

[quote=“sinisoul, post:4, topic:409572”][quote author=ollie123 link=topic=510852.msg3707143#msg3707143 date=1313107651]

I might try and implement the Nihilist cipher next :P.
[/quote]

Not what I meant, http://en.wikipedia.org/wiki/Feistel_cipher[/quote]

Right. I’ll have to look over that first. Heard of it before though.


#6

hi let’s write implementations of outdated, useless ciphers for no reason whatsoever.


#7

hi let’s fuck off of threads that are of no interest to us


#8

[quote=“ollie123, post:7, topic:409572”][quote author=(Anthony) link=topic=510852.msg3707505#msg3707505 date=1313122768]
hi let’s write implementations of outdated, useless ciphers for no reason whatsoever.
[/quote]

hi let’s fuck off of threads that are of no interest to us[/quote]
Hi let’s get back on topic before I decide to lock and ban.


#9

Anyway, I can assure you it is solely to gain experience.


#10

[quote=“ollie123, post:9, topic:409572”][quote author=(Anthony) link=topic=510852.msg3707505#msg3707505 date=1313122768]
hi let’s write implementations of outdated, useless ciphers for no reason whatsoever.
[/quote]

Anyway, I can assure you it is solely to gain experience.[/quote]
what the fuck kind of “experience” do you gain from this…


#11

[quote="(Anthony), post:10, topic:409572"][quote author=ollie123 link=topic=510852.msg3707996#msg3707996 date=1313168928]

Anyway, I can assure you it is solely to gain experience.
[/quote]
what the fuck kind of “experience” do you gain from this…[/quote]

Anything programmed is experience for me, didn’t even start that long ago.


#12

[quote=“ollie123, post:11, topic:409572”][quote author=(Anthony) link=topic=510852.msg3708140#msg3708140 date=1313177095]

what the fuck kind of “experience” do you gain from this…
[/quote]

Anything programmed is experience for me, didn’t even start that long ago.[/quote]
who cares, you’ll learn more implementing something that’s useful.


#13

:rolleyes:

Are you two done being… well, /useless/ assholes yet? You guys appear to be even more concerned with what he programs than he is himself… I don’t know what kind of sick obsessions you have, but this is not a healthy, nor constructive, might I add, way to express them :o

I’m glad to see you applied the criticism on access modifiers in mdog311’s thread. Good work :slight_smile:


#14

i’m still pretty certain he’d learn more implementing something that is useful nowadays rather than something that was probably breakable back in the 60s…


#15

Very nice. I was going to write an implementation, but at the rate I switch projects/interests I never got around to :stuck_out_tongue:

Some of us write things because we’re bored and decide to do the first thing that pops into our heads. That’s why I made the Playfair.


#16

Hi my name is general box
:open_mouth: ,anyway with regards to this program which is very easy to follow and that is saying something, but hey what is up with the try and catch exception error instructions thrown in to middle of the public static main void method and not filling in the constructor and initialising the method, it won’t work obviously without these important instruction’s and I desperately need this to get the cipher to initialise and work, the code otherwise looks great, why cut at the crucial moment, it only activates the try and catch statements as array index out of bounds exception, because I think there is no proper main or runner class instigated, can you please help, the code seems incomplete, help morphasis the best, please !!!
Need this foursquare to perform for a cool unbreakable cipher project !!


#17

wow I actually posted this lolol


#18

The program isn’t incomplete: all the methods are static so there is no need for a constructor or a FourSquare object to be instantiated. A Try-Catch clause will automatically execute what’s in the Try block first and if there’s an exception it will execute what’s in the Catch block.

All that aside, this is a pretty extreme grave dig. Not only that, but if you think this is any basis for an “unbreakable” cipher project, you are sorely misguided.


#19

Hi, U

Thanks for replying, I am really new to java and find it tricky enough to follow, anyway when I run this code it outputs the usage option displaying usage [-d] <plaintext/ciphertext> and so on but it does not allow me to enter anything like a keyword or a text file to either decrypt or encrypt it just responds with cannot find that command and there is no menu option displayed to allow you to select, only the usage option appears from the last line of catch statement, don’t understand could you enlighten me if you know what the issue might be it would be great and educational.


#20

The program accepts 4 (1 optional) commandline arguments. Once you compile the program with javac e.g. “javac FourSquare.java” and obtain your classfile “FourSquare.class”, you run it with “java FourSquare TextIWantToEncrypt keyword1 keyword2”. The output will be text encrypted using the FourSquare algorithm.

The optional first argument (the -d specifier) is when you want to decrypt the encrypted text you received from above e.g. “java FourSquare -d EncryptedTextYouRecievedFromAbove keyword1 keyword2”. The output will be decrypted text encrypted using the FourSquare algorithm.

I explained it as if you’re running it from the console, so if you use an IDE you’ll have to figure out where you can set command line arguments in Settings, or if you use a console e.g. click on the Windows start menu and select run then type cmd, just type it as shown above.