-2

I am working on a caesar cipher program as my final project in java I. I have a method for the encryption that handles lower and uppercase characters. However I have hit a wall trying to adjust the algorithm to work the shift factor in the opposite direction to decrypt text already run through the program.

Another issue is that I cannot make the program work with spaces, either ignoring them or encrypting them as well. So far it only encrypts the first word and ignores the rest. Here is my encryption method thus far, with the message passed from main() as a parameter.

//Caesar Cipher
public class EncryptionClass1 { 
     protected static String encryptedMessageString;

    public static String setEncryptedMessage(String message) { 
        StringBuffer encryptedMessageBuffer = new StringBuffer();
        char newCharacter;
        int shiftFactor = 1;
        int i;

             //for length of secret message
          for (i = 0; i<message.length(); i++) { 
            //uppercase encoder
            if (Character.isUpperCase(message.charAt(i))) { 
                newCharacter = (char)(((int)message.charAt(i) - 
                                  shiftFactor - 65) % 26 + 65); 
                encryptedMessageBuffer.append(newCharacter);          
            }//if close 

            //lowercase encoder
            else { 
                newCharacter = (char)(((int)message.charAt(i) - 
                                  shiftFactor - 97) % 26 + 97); 
                encryptedMessageBuffer.append(newCharacter); 
            }//else close 

          }//for close 
        //convert StringBuffer to string 
        encryptedMessageString = encryptedMessageBuffer.toString();
        return encryptedMessageString;  

    }//setEncryptedMessage close  
}//EncryptionClass1 close 

For the decryption, I figure that I only need to adjust some of the operations for the encryption method, but I cant pinpoint what.

as for the spaces, an input and output example should be as follows:

Input: “my secret message”
Output: rp dbxbbf rbddtfb
jeb
  • 17
  • 2
  • So you're only asking about skipping spaces? Which means that you got everything else working already? Then show what you have, and we can help you enhance that to skip spaces correctly. If you don't have the other parts yet, work on that first, then figure out how to skip spaces after that. Right now, this question is **too broad**. – Andreas May 09 '19 at 00:32
  • *"In pseudocode I'm thinking it would look like this.."* Like what? I see no pseudocode. – Andreas May 09 '19 at 00:32
  • So sorry I accidentally posted the question before I finished. I edited my original post with more information. Thank you. – jeb May 09 '19 at 00:35
  • I see no encryption logic in all that code. You've shown us irrelevant code. Seems the encryption logic is in the `setEncryptedMessage` method, so maybe it would be better if you remove all that useless code (useless from the questions point of view), and instead show us the actual code you need help with, don't you think? – Andreas May 09 '19 at 00:40
  • *FYI:* `scnr.next()` will only return one token (word), so the message will not contain any spaces. If you want message with spaces, use `scnr.nextLine()` instead. Beware of this issue: [Scanner is skipping nextLine() after using next() or nextFoo()](https://stackoverflow.com/q/13102045/5221149) – Andreas May 09 '19 at 00:44
  • edited with proper code, sorry once again – jeb May 09 '19 at 00:51
  • see https://stackoverflow.com/questions/35242376/java-caesar-cipher-code for decrypt examples – Jeremy Kahan May 09 '19 at 02:15

1 Answers1

2

To shift in the opposite direction, shift further in the current direction. Visualize the 26 letters of the alphabet on a 360° dial. If encryption is to rotate (shift) the dial 5 letters to the right, you'd normally think of decryption as rotating the dial 5 letters to the left. But you could also rotate the dial 21 (26 - 5) letters to the right. So, if encryption is shifting shiftFactor up, then decryption is shifting 26 - shiftFactor up. By only shifting up, the % 26 operation will correctly wrap the shift around.

Since the encrypted message is always exactly the same length as the original message, and you only replace one letter at a time, the code will be simpler if you just work on a char[] from the original message. If you do that, then simply skip characters in the array that are not ASCII letters.

Instead of using magic numbers 65 and 97 , use their char values to make the code more readable.

All of the above means that your code could be written like this:

private static final int SHIFT_FACTOR = 5;

public static String encryptMessage(String message) {
    return applyShift(message, SHIFT_FACTOR);
}

public static String decryptMessage(String message) {
    return applyShift(message, 26 - SHIFT_FACTOR);
}

private static String applyShift(String message, int shiftFactor) {
    char[] chars = message.toCharArray();
    for (int i = 0; i < chars.length; i++) {
        char c = chars[i];
        if (c >= 'A' && c <= 'Z')
            chars[i] = (char) ((c - 'A' + shiftFactor) % 26 + 'A');
        else if (c >= 'a' && c <= 'z')
            chars[i] = (char) ((c - 'a' + shiftFactor) % 26 + 'a');
    }
    return new String(chars);
}

Test

public static void main(String[] args) {
    test("my secret message");
    test("Hello World!");
}
private static void test(String message) {
    String encrypted = encryptMessage(message);
    System.out.println("Input    : " + message);
    System.out.println("Encrypted: " + encrypted);
    System.out.println("Decrypted: " + decryptMessage(encrypted));
    System.out.println();
}

Output

Input    : my secret message
Encrypted: rd xjhwjy rjxxflj
Decrypted: my secret message

Input    : Hello World!
Encrypted: Mjqqt Btwqi!
Decrypted: Hello World!
Andreas
  • 138,167
  • 8
  • 112
  • 195