Need explanation for code in Caesar cipher - java

Hey so recently I got tasked with creating an app that reads a message and ecrypts it with the Caesar cipher in Java.
I didn't really have a problem until I came to the part where adding the numberic cipher would take you over letters a-z/A-Z into special symbols and I did not really know what to do.
Here is the code of my solution:
private String caesarCipher(String message) {
Scanner input = new Scanner(System.in);
StringBuilder cipher = new StringBuilder();
char ch;
int key;
System.out.print("Enter a key: ");
key = Integer.parseInt(input.nextLine());
for(int i = 0; i < message.length(); i++) {
ch = message.charAt(i);
if(ch >= 'a' && ch <= 'z'){
ch = (char)(ch + key);
if(ch > 'z'){
ch = (char)(ch - 'z' + 'a' - 1);
}
cipher.append(ch);
}
else if(ch >= 'A' && ch <= 'Z'){
ch = (char)(ch + key);
if(ch > 'Z'){
ch = (char)(ch - 'Z' + 'A' - 1);
}
cipher.append(ch);
}
else {
cipher.append(ch);
}
}
return cipher.toString();
}
Could someone please explain to me the process and reasoning behind the following statement:
if(ch > 'z'){
ch = (char)(ch - 'z' + 'a' - 1);
}

It will never allow an encrypted character to exceed its supposed range, that is, a - z. The ascii of a and z are 97 and 122 respectively, and you would want the Caesar cipher encryption within this range of characters only.
This will check if the ascii code of ch is greater than the ascii of z
if(ch > 'z'){
If yes, it will calculate: (ascii of ch) - (ascii of z) + (ascii of a) - 1.
ch = (char)(ch - 'z' + 'a' - 1);
It is translated into ch = (char)(ch - 122 + 97 - 1);
Suppose you want to encrypt character a with a key 3. The program will take 97 (ascii of a) + 3. You will get 100, which is the ascii of d. Yet, what if you want to encrypt z with a key 3?
Same as before, it will take 122 (ascii of z) + 3 = 125. However, 125 is not found in the range 97 - 122 (a-z). Thus, you will get an unwanted character (in this case, 125 is the ascii of }).
Therefore, (ch - 'z' + 'a' - 1) will ensure that any character exceeding ascii 122, will be converted back into a character with ascii range of 97 and 122 inclusive only. In the example of 125, ch = (char)(125 - 122 + 97 - 1) => ch = (char)(99) => ch = c.

Related

Java - queastion on purpose of (char){Alphabet - "a" + "z" + 1}

Essentially, I am confused on the purpose of this code and what it does ( cAlphabet = (char)(cAlphabet - 'a' + 'z' + 1); ), in this encryption code, could someone please explain how this works thanks!
System.out.println(" Input the ciphertext message : ");
String ciphertext = sc.nextLine();
System.out.println(" Enter the shift value : ");
int shift = sc.nextInt();
String decryptMessage = "";
for (int i = 0; i < ciphertext.length(); i++)
{
// Shift one character at a time
char alphabet = ciphertext.charAt(i);
// if alphabet lies between a and z
if (alphabet >= 'a' && alphabet <= 'z')
{
// shift alphabet
alphabet = (char)(alphabet + shift);
// shift alphabet less than 'a'
if (cAlphabet < 'a')
{
//reshift to starting position
cAlphabet = (char)(cAlphabet - 'a' +'z' + 1);
}
cAlphabet = (char)(cAlphabet - 'a' + 'z' + 1);
When you make some operations(sum, minus, etc) with Char it wiil use numeric code of character. So you will get new numeric code and convert it back to the character.
this is almost the same as cAlphabet = (char)(cAlphabet - 219 + 97 + 1);

restore original word after Caesar Cipher shifting

I write a func of Caesar Cipher.
So after I shift a sentence, I want also shift back to the original sentence.
For now it works only for one direction, when I shift with natural positive number, but when I try to do this with negative number, it goes on to value less than 97 of ascii lowercase letters.
I give an example:
word: java
key = 10
output: tkfk
Now I want to shift back, to restore my word from tkfk to java.
key = -10
output: ja\a
Instead of v it put \
I know its happens couse from f to minus 10 from ascii table is the letter '\' and I want the letter v.
I think I need to manipulate this line, but I dont know how, I'm a little bit stuck and I don't have an idea what to do.
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97)
My method: (little bit long)
public static void MakeCipherText(String[] text, int key) {
int index =0;
if (key > 0) {
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in every itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
} else { // key is negetive number
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in evry itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
}
}
Any suggestion?
As the comments suggest you should really check your code again this will also help you to be a better programmer. But anyway you think too complicated.
If you check your else part that is the exact copy of the if part. And that is no wonder. To decode Caesar cipher you encode it basically again with the right key to encode.
For example:
If you encode it with A => B or in this example with 1:
test--> uftu
so how can we decode uftu back?
When we shift it with B=>A or in this case with 25.
uftu --> test
So in your requirement you want if you put -1 that you decode text that was encoded with 1 before.
So basically we have to find a method to map -1 to 25, -2 to 24 and so on.
And the key function is: modulo
-2 % 26 => 24
-1 % 26 => 25
...
In addition you can even now put numbers bigger than 26 because:
500 % 26 => 6
-500 % 26 => 20
and because 2 % 26 => 2 you don't even need that if clause. Your code looks like this in the end:
public static void MakeCipherText(String[] text, int key) {
int index =0;
key = (((key % 26) + 26) % 26); // See below for explanation of this weird modulo
if( text[index] == null || text[index].equals("")) {
System.out.println("No sentences to fix capital letters.");
} else {
while(text[index] != null && !text[index].equals("")) { // only if we have sentence in array or array not contain empty sentence we go through loop
String chiPstr = "";
for(int i=0; i<text[index].length(); i++) {//we work in every itration on 1 sentence (1 index of str array)
if(Character.isLowerCase(text[index].charAt(i))) {//if we have lower letter than:
char ch = (char) (((int) text[index].charAt(i) + key-97) % 26+97); //we put asci value + Cipher value
chiPstr = chiPstr + ch; //each time we add to the new sentece the result
} else if(Character.isUpperCase(text[index].charAt(i))) {//same thing like here, but its work on uppercase letters.
char ch = (char) (((int) text[index].charAt(i) + key-65) % 26+65);
chiPstr = chiPstr + ch;
}else {// if we have space, or other characters that is no a letter, we just put him as is in a sentence.
chiPstr = chiPstr + text[index].charAt(i);
}
}
text[index] = chiPstr;
index ++;
}
}
}
Never forget to use functions and don't use duplicate code. Bad style and error prone. The solution is quite easy if you think it through.
Information weird modulo function
You see I use a weird modulo function. Because in Java % don't calculate the modulo but the remainder. (Different then in Python).
So to get the "true" modulo in Java we have to use this weird trick:
Reference: What's the difference between “mod” and “remainder”?
key = (((key % 26) + 26) % 26);

Encode/Decode a String with x chars, with the factor n. [Java]

I am quite at a loss here, i am to create a java programm which takes a String and decodes/encodes the string with n.(It adds n to the chars of the string like n=3 a=c) I buitl the "shell" which takes the user to the action he would like the programm to perform, then i dont get how to encode/decode the string with the key, it has to consider upper/lowercase and ignore special symbols like )/!/&"$;:.,, there has to be something with "for" and a chararray which i never worked with before and do not understand...
All help appreciated!
heres the code so far! https://gist.github.com/fabiomim/070d1daeee4b604db720adf7c7dff240
(ignore the little rant in fachklasse)
Some hints:
you can get the characters by using the charAt(int) or toCharArray() methods of String:
String string = ...
char ch = string.charAt(i);
// or
char[] characters = string.toCharArray();
char ch = characters[i];
A char is a Integral Type, that is, an integer type and you can do arithmetic with it, like comparison, addition, subtraction:
char ch = ...
if (ch >= 'a' && ch <= 'z') {
// do something it the char is between 'a' and 'z'
ch += 3; // 'a' will become 'd', 'z' will be '}'!!!!
if (ch > 'z') {
// handle overflow like subtracting 'z'+1 - 'a'
}
}
To create a String from the char array, you can use:
String result = new String(characters);
Note that a char is not an int, you need a cast to assign it to a char variable:
ch = ch + 3; // ERROR since "ch + 3" is an int
ch = ch + 'a'; // ERROR the result of + is still an int!
ch = (char) (ch + 3);
ch = (char) (ch + 'a');

caesar shift cipher java

I'm trying to implement a basic Caesar Shift Cipher for Java to shift all the letters by 13. Here's my code so far.
public static String cipher(String sentence){
String s = "";
for(int i = 0; i < sentence.length(); i++){
char c = (char)(sentence.charAt(i) + 13);
if (c > 'z')
s += (char)(sentence.charAt(i) - 13);
else
s += (char)(sentence.charAt(i) + 13);
}
return s;
}
However, the program also changes the values of numbers and special characters and I don't want that.
String sentence = "abc123";
returns "nop>?#"
Is there a simple way to avoid the special characters and only focus on letters?
Edit: I should mention I want to keep all the other bits. So "abc123" would return "nop123".
In the following example I encrypt just the letters (more precisely A-Z and a-z) and added the possibility to use any offset:
public static String cipher(String sentence, int offset) {
String s = "";
for(int i = 0; i < sentence.length(); i++) {
char c = (char)(sentence.charAt(i));
if (c >= 'A' && c <= 'Z') {
s += (char)((c - 'A' + offset) % 26 + 'A');
} else if (c >= 'a' && c <= 'z') {
s += (char)((c - 'a' + offset) % 26 + 'a');
} else {
s += c;
}
}
return s;
}
Here some examples:
cipher("abcABCxyzXYZ123", 1) // output: "bcdBCDyzaYZA123"
cipher("abcABCxyzXYZ123", 2) // output: "cdeCDEzabZAB123"
cipher("abcABCxyzXYZ123", 13) // output: "nopNOPklmKLM123"
Note: Due to your code, I assumed that you just want to handle/encrypt the "ordinary" 26 letters. Which means letters like e.g. the german 'ü' (Character.isLetter('ü') will return true) remain unencrypted.
Problem is that you add 13 as a fixed number, and that will for some letters (in second half of alphabet mostly and digits) produce characters that aren't letters.
You could solve this by using array of letters and shifting through those characters. (similar for digits) So something like this
List<Character> chars = ... // list all characters, separate lists for upper/lower case
char c = chars.get((chars.indexOf(sentence.charAt(i)) + 13)%chars.size());

Caeasar Cipher with java's acm

The code below encrypts a word or sentence in the way Caesar did. You put the shift value and the program takes each letter of the word/sentence and "moves" in the alphabet acoording to the shift (key) value. But this is not the problem.
I found the code on the internet and i cannot explain some of it's lines.
I know how it works but i need some specific answer about some of it's lines.
Here is the code:
import acm.program.*;
public class CaesarCipher extends ConsoleProgram {
public void run() {
println("This program implements a Caesar cipher.");
int key = readInt("Character positions to shift: ");
String plaintext = readLine("Enter a message: ");
String ciphertext = encodeCaesarCipher(plaintext, key);
println("Encoded message: " + ciphertext);
}
private String encodeCaesarCipher(String str, int key) {
if (key < 0) key = 26 - (-key % 26);
String result = "";
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (Character.isLetter(ch)) {
if (Character.isUpperCase(ch)) {
ch = (char) ('A' + (ch - 'A' + key) % 26);
}
else {
ch = (char) ('a' + (ch - 'a' + key) % 26);
}
}
result += ch;
}
return result;
}
}
What exactly do those lines mean, and how do they do what they do?
ch = (char) ('A' + (ch - 'A' + key) % 26);
and
ch = (char) ('a' + (ch - 'a' + key) % 26);
Those two lines behave identically, except for the fact that one applies to uppercase, and one to lowercase. I'll explain the uppercase operations here. Keep in mind that these char values are treated as ints until step 6 below.
ch = (char) ('A' + (ch - 'A' + key) % 26);
ch - 'A' gives the initial character's int offset from capital-A.
ch - 'A' + key increases the offset by key, creating the ciphered character's offset from capital-A.
(ch - 'A' + key) % 26: the modulo here ensures that the numeric value of the ciphered character is 0-25 (for the 26 letters in the alphabet), preventing alphabet "overflow." The value of that expression is now the normalized offset of the ciphered character from capital-A.
'A' + (ch - 'A' + key) % 26 adds the ciphered character's offset from capital-A to capital-A itself, resulting in the ciphered character's int value.
(char) ('A' + (ch - 'A' + key) % 26) casts that int to char type, resulting in the ciphered character as a char.
This code treats the beginning of the alphabet (capital-A) as the "starting point," from which each letter's offset is measured. The offset is the character's number of letters from 'A'.
Example: To cipher "E" with a key of 6:
Find the number of letters between "E" and capital-A. The ASCII code of A is 65, and the code of E is 69. To find E's offset from A, subtract 69 - 65 = 4.
Add the offset and the key: 4 + 6 = 10. This is the number of letters from A the ciphered character will be.
10 % 26 = 10 (no effect because of the small starting letter + small key)
'A' + 10 = 65 + 10 = 75 results in the ASCII code of the ciphered character, 75 ('K')
Casting 75 to char allows it to be treated as a character, rather than an int.
It is converting the character to the ASCII equivalent, as denoted by the + operator (you cannot add characters, only numbers), then changing the character by a certain number of values. The (char) is casting (converting) the result back to a character so you can assign it to ch.
'A's ASCII value is 65, and ch is the character currently being evaluated at position i in the string. ch = (char) ('A' + (ch - 'A' + key) % 26); evaluates as '65 + (character's ASCII number - 65 + key) % 26'. This result is then cast back to a character and assigned to ch. The modulo (%) operator takes a number, divides it by a second number, in this case 26, and returns the remainder (5 % 6 is 5, while 7 % 3 is 1). The second statement works the same way, but uses lowercase 'a' (97) instead of capital 'A'.
See this page for ASCII keys: http://www.asciitable.com/

Categories