Wednesday, 15 July 2009

Brute force TrueCrypt when you sort of know the password.

So a friend asked me to generate all possible combinations of two words, he uses two words as passwords and mixes up the capitalisation of those words so that if he has the two words "apple" and "pears" as possible passwords then he could have something like "aPpRe"... there are loads of possibilities but not as many as there could be because each letter position would only have 4 possible letters. For example the third letter can only be "p", "P", "a" or "A". Mathematically we're looking at four possible outcomes for a one letter password, sixteen for a two letter word, 64 for a three letter word... 256... 1024... 4096... 16384... 65536... 262144... 1048576 for a ten letter password.

Doing it by hand is just about possible if you're only looking at a 3 letter combination but otherwise...

Seeing as I'm relearning Java I thought I'd have a crack (after getting lots and lots of help from comp.lang.java.help - I did say relearning!) and after trying to get my head around recursion and realising I'd done something with it years ago using JavaScript to parse an OWL file representing the management structure of an organisation I came up with the following file:

WordComb.java:

public class WordComb {
  public static void main (String[] arguments ){
    if (arguments.length != 2) {
      System.out.println("This program requires two arguments, please try again.");
    }
    else {
      if (arguments[0].length() != arguments[1].length()){
        char spaceChar = ' ';
        int argOne = arguments[0].length();
        int argTwo = arguments[1].length();
        if (argOne < argTwo) {
          for (int a = argOne; argOne < argTwo; argOne++){
            arguments[0] = arguments[0]+spaceChar;
          }
        }
        else {
          for (int a = argTwo; argTwo < argOne; argTwo++){
            arguments[1] = arguments[1]+spaceChar;
          }
        }
      }
      char[][] words  = {arguments[0].toLowerCase().toCharArray(),
                         arguments[0].toUpperCase().toCharArray(),
                         arguments[1].toLowerCase().toCharArray(),
                         arguments[1].toUpperCase().toCharArray()};
      char[] combo = new char[words[0].length];
      fill(combo, words, 0);
    }
  }
  public static void fill(char[] combo, char[][] words, int col) {
    if (col < combo.length) {
      for (char[] row : words) {
        combo[col] = row[col];
        fill(combo, words, col+1);
      }
    }
    else {
      System.out.println(makeString(combo));
    }
  }
  public static String makeString(char... word) {
    return String.valueOf(word).trim();
  }
}

All that needs is a little command-line redirection and you've a nice file to feed into your TrueCrypt cracker of choice...