/** ------------------------------------------------------------------------ * Decrypt.java * This is a decryption program using a combination of: * 1. transposition (e.g. for a transposition of 1, "abc" becomes "bce", * and "xyz" becomes "yza") * 2. reversing direction of each word (e.g. "abc" becomes "cba") * 3. using a Vigenere cipher (see wikipedia article on Vigenere cipher) * * Program takes about 15 seconds to run. This could be sped up if we assume that all words * in the cipherText are in the dictionary, and abort considering a case when a word is not * found in the dictionary.1 * * Class: CS 107 * Lab: Englebert Humberdink, Mon. 5:00 AM * System: Eclipse 3.3.2, Java sdk 1.6, Windows XP * * @author Dale Reed * @version March 29, 2009 * * Running program gives: * Author: Dale Reed Program 4: Decryt TA: Billie Joe Armstrong, T 6:00 AM March 29, 2009 Choose from the following options: 1. Encode some text 2. Decode using user-entered values 3. Decode the ciphertext given with the assignment 4. Exit program Your choice: 1 Enter the text to be encoded: all generalizations are false Enter direction (Forwards or Reverse): reverse Enter transposition value (0..25): 3 Enter a keyword for Vigenere encryption: secret Keyword is:secret Keyword, plainText and ciphertext are: secretsecretsecretsecretsecret all generalizations are false gsf zjjpyugeghwyuab jlh zzqum * * And again running program gives: * * Author: Dale Reed Program 4: Decryt TA: Billie Joe Armstrong, T 6:00 AM March 29, 2009 Choose from the following options: 1. Encode some text 2. Decode using user-entered values 3. Decode the ciphertext given with the assignment 4. Exit program Your choice: 2 Enter the cipherText to be decoded: gsf zjjpyugeghwyuab jlh zzqum Enter the Vigenere keywords to be tried: one secret two ciphertext is: gsf zjjpyugeghwyuab jlh zzqum String of possible keywords is: one secret two New best case. Dictionary hits: 1, keyword: one, transposition: 3, direction: Forwards vie piyfxjwdvxvnkzq iax oppjc New best case. Dictionary hits: 3, keyword: secret, transposition: 23, direction: Reverse all generalizations are false Decrypted text is: all generalizations are false * * And again running program gives: * Author: Dale Reed Program 4: Decryt TA: Billie Joe Armstrong, T 6:00 AM March 29, 2009 Choose from the following options: 1. Encode some text 2. Decode using user-entered values 3. Decode the ciphertext given with the assignment 4. Exit program Your choice: 3 ciphertext is: IQHN OH XALM EJG JYOQ NBGNRV KMBQJ ZTNZZV BH QIQWSHY OH GF RTKHM JUUQOW AHUGX TBGJZZ OIQG KZTG MAY JCYR GZI YS MAY KWDDB String of possible keywords is: students i hope you are learning how to use a computer they can be tricky but powerful when you figure out how to use them in addition having technical skills can advance your career in ways you would not otherwise in any case this course will be over in about five weeks New best case. Dictionary hits: 1, keyword: students, transposition: 6, direction: Forwards wdtq hu lnxp xwu wkrs apuady dzpew cvgmnj nk jvekftb hu us uvdua wgxshj ougjz gpuwlc hveu wcvz aol mere umu al aol nywqp New best case. Dictionary hits: 4, keyword: students, transposition: 12, direction: Reverse wzjc an vdtr acd yxqc ejgavg ckvfj ptsmbi qt hzlqkbp an ya gajba pnydmc fpmau ircavm akbn fbic rug kxks asa rg rug vwcet New best case. Dictionary hits: 24, keyword: computer, transposition: 9, direction: Reverse help me give you five points extra credit by sending me an email before march twenty nine with the word fun in the title Decrypted text is: help me give you five points extra credit by sending me an email before march twenty nine with the word fun in the title Exiting program... * ---------------------------------------------------------------------------- */ // import Java libraries that are needed import java.util.Scanner; // used for console input // the following are needed to implement reading from the dictionary import java.io.IOException; // for IOException import java.util.ArrayList; // Used to create ArrayLists dictionary use import java.io.*; // Used for IOException, File // Declare the class public class DecryptText107 { // Fields that can be accessed anywhere in the class go here Scanner keyboard = new Scanner( System.in); // used to read user input // Declare a dynamically allocated ArrayList of Strings for the dictionary. // The dictionary can hold any number of words. ArrayList dictionary; // Fields to store best case found int BestNumberOfDictionaryHits = 0; // will range from 0 to # of input words String BestKeyword = ""; // will be a single word from list of possible words int BestTranspositionValue = 0; // 0..25 String BestDirection = "Forwards"; // will be "Forwards" or "Reverse" // Store the Vigenere Table char[][] vigenereTable; //-------------------------------------------------------------------------- // main() - startup main loop. It is necessary to create an instance of this // class and then call a method from that instance, otherwise there may // be error messages having to do with non-static objects (e.g. keyboard) // being called from a static context (e.g. main). // The words "throws IOException" have to do with dictionary error // handling. // public static void main(String[] args) throws IOException { // create an instance of this class DecryptText107 DecryptTextInstance = new DecryptText107(); // call a non-static method to do everything else DecryptTextInstance.mainLoop(); System.out.println("\n" + "Exiting program...\n"); } //------------------------------------------------------------------------- // mainLoop() - display identifying information and run main loop with menu // The words "throws IOException" have to do with dictionary error // handling. // void mainLoop() throws IOException { // First take care of creating and initializing the dictionary // Define the instance of the dictionary ArrayList dictionary = new ArrayList(); // Now fill the dictionary array list with words from the dictionary file readInDictionaryWords(); // Allocate space for the Vigenere table used in decoding vigenereTable = new char[26][26]; // fill the table with letters of the alphabet, transposing each row by 1 for( char row=0; row<26; row++){ for( int column=0; column<26; column++) { vigenereTable[ row][ column] = (char) ((row + column)%26 + 'a'); }//end for( int column... }//end for( char... String cipherText = ""; // stores user Input in main loop String keyWordsInput = ""; // stores keywords input // Display identifying information System.out.println( "Author: Dale Reed \n" + "Class: CS 107, Spring 2009 \n" + "Program 4: Decryt \n" + "TA: Billie Joe Armstrong, T 6:00 AM \n" + "March 29, 2009\n"); // Prompt for input to be used System.out.println("Choose from the following options:"); System.out.println(" 1. Encode some text "); System.out.println(" 2. Decode using user-entered values "); System.out.println(" 3. Decode the ciphertext given with the assignment "); System.out.println(" 4. Exit program "); System.out.print("Your choice: "); String menuChoice = keyboard.nextLine(); // handle user input if( menuChoice.equals("1") ) { promptForEncoding(); // skip rest of code System.exit( 0); } else if( menuChoice.equals("2")) { // set values to use in decoding of some user-entered String System.out.print("Enter the cipherText to be decoded: "); cipherText = keyboard.nextLine(); System.out.print("Enter the Vigenere keywords to be tried: "); keyWordsInput = keyboard.nextLine(); } else if( menuChoice.equals("3")) { // set values used in decoding for this assignment cipherText = "IQHN OH XALM EJG JYOQ NBGNRV KMBQJ ZTNZZV BH QIQWSHY " + "OH GF RTKHM JUUQOW AHUGX TBGJZZ OIQG KZTG MAY JCYR GZI YS MAY KWDDB"; keyWordsInput = "Students I hope you are learning how to use a computer They can be tricky " + "but powerful when you figure out how to use them In addition having " + "technical skills can advance your career in ways you would not otherwise " + "In any case this course will be over in about five weeks"; } else if( menuChoice.equals("4") ) { System.out.println("Exit was chosen."); // skip rest of code System.exit( 0); } else { System.out.println("Invalid menu option chosen. Please re-run program"); // skip rest of code System.exit( 0); } // Display values that will be used System.out.println("ciphertext is: " + cipherText); // convert to all lower case cipherText = cipherText.toLowerCase(); // keep track of how many words are in the cipherText. If our dictionary lookup // equals this number, we can quit, assuming this is the answer. Compute this by // creating an array of the cipherText words (using split()) and then finding the length // of this array. int numberOfWords = cipherText.split(" ").length; // convert to all lower case keyWordsInput = keyWordsInput.toLowerCase(); System.out.println("String of possible keywords is: " + keyWordsInput); // make an array of strings by splitting the input line at spaces String[] keyWordsInputArray = keyWordsInput.split(" "); int numberOfDictionaryHits = 0; // store number of words found in dictionary for each case // Try the various possible Vigenere keywords, one at a time for( int i=0; i BestNumberOfDictionaryHits) { // we have a new best case BestNumberOfDictionaryHits = numberOfDictionaryHits; BestKeyword = keyWord; BestTranspositionValue = transpositionValue; BestDirection = direction; // display values for debugging System.out.println("New best case. Dictionary hits: " + numberOfDictionaryHits + ", keyword: " + keyWord + ", transposition: " + transpositionValue + ", direction: " + direction + "\n" + cipherText + "\n"); }//end if( numberOfDictionaryHits... }//end storeBestCase(...) // Read in the words to create the dictionary. // It throws an IOException, which is a way to gracefully handle errors // should there be a problem reading from the input. public void readInDictionaryWords() throws IOException { // Define a Scanner to read from an input file. Note that the name of // the file given in the code below MUST match the actual filename of // the dictionary file. This file should be in the same directory // as the source code for WordCross.java File dictionaryFile = new File("dictionary.txt"); // declare the file // print the directory where this program expects to find dictionary System.out.println(System.getProperty("user.dir")); // ensure file exists and is in the correct directory if( ! dictionaryFile.exists()) { System.out.println("*** Error *** \n" + "Your dictionary file has the wrong name or is " + "in the wrong directory. \n" + "Aborting program...\n\n"); System.exit( -1); // Terminate the program } Scanner inputFile = new Scanner( dictionaryFile); // while there are words in the input file, add them to the dictionary while( inputFile.hasNext()) { dictionary.add( inputFile.nextLine() ); } }//end createDictionary() // Allow looking up a word in dictionary, returning a value of true or false public boolean wordExists( String wordToLookup) { if( dictionary.contains( wordToLookup)) { return true; // words was found in dictionary } else { return false; // word was not found in dictionary } }//end wordExists // Transpose each letter in a string by a certain amount. // Letters in the original string are all folded into upper case. public String transposeString( String originalString, int transposition) { // if transposition is a negative number convert it to the equivalent // positive number. In other words transposing by 26 is the same as // transposing by 0, and transposing by -1 is the same as transposing by 27 if( transposition < 0) { transposition = 26 + transposition; } // fold into all lower case originalString = originalString.toLowerCase(); // declare an array which is same size as original string char[] newLetters = new char[ originalString.length()]; // step through each letter in original string, transposing it for( int i=0; i