// VigCipher.java // A solution to CS 10 assignment 5, part 2, Fall 2008 // cmc, 11/18/08 /** A Vigenere cipher. */ public class VigCipher implements Cipher { private String key; /** Constructs a VigCipher object. @param aKey the encryption key. */ public VigCipher(String aKey) { key = aKey.toLowerCase(); } /** Encrypts the text according to the Vigenere Cipher described in Exercise P19.3, pp. 840-841, Horstmann's Big Java 3rd Edition. Only processes the letters A-Z and a-z, preserving capitalization and leaving all other characters unchanged (also does not increment the substitution order of the encryption key for non-letters). @param text the text to encrypt. @return the encrypted text. */ public String encrypt(String text) { return process(text, false); } /** Decrypts the text according to the Vigenere Cipher. Here it is assured that if c is a VigCipher and s is a String, then s is equal to c.decrypt((c.encrypt(s))). @param text the encrypted text to decrypt. @return the decrypted text. */ public String decrypt(String text) { return process(text, true); } // utility processes the text according to the boolean parameter private String process(String text, boolean decrypting) { StringBuilder result = new StringBuilder(); int nKey = 0; // used to track index of current key character final char A = 'a'; final int N = 26; final int KEY_LEN = key.length(); for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); // current text character // just append non-letters unchanged and don't increment key char if (!Character.isLetter(c)) result.append(c); else { // store current key character and move index to next one char k = key.charAt(nKey); nKey = (nKey + 1) % KEY_LEN; // offset of current key character (from start of alphabet) int kOffset = k - A; if (decrypting) kOffset = N - kOffset; // find the new character to replace the current one int cOffset = Character.toLowerCase(c) - A; int newOffset = (cOffset + kOffset) % N; char newChar = (char)(A + newOffset); // maintain capitalization of original character if (Character.isUpperCase(c)) newChar = Character.toUpperCase(newChar); result.append(newChar); } } return result.toString(); } }