|
| 1 | +--- |
| 2 | +title: Create a Caesar Cipher with Java |
| 3 | +author: Ellie Popoca |
| 4 | +uid: 11zhRKeJCWWcD7IkTJBtuK3Mkvo1 |
| 5 | +datePublished: |
| 6 | +published: false |
| 7 | +description: Learn how to make a caeser cipher encrypter with Java using the Scanner class. |
| 8 | +header: https://raw.githubusercontent.com/codedex-io/projects/main/projects/create-a-caesar-cipher-with-java/header.gif |
| 9 | +tags: |
| 10 | + - intermediate |
| 11 | + - java |
| 12 | +--- |
| 13 | + |
| 14 | +<BannerImage |
| 15 | + link="https://raw.githubusercontent.com/codedex-io/projects/main/projects/create-a-caesar-cipher-with-java/header.gif" |
| 16 | + description="Title Image" |
| 17 | + uid={true} |
| 18 | + cl="for-sidebar" |
| 19 | +/> |
| 20 | + |
| 21 | +# Create a Caesar Cipher with Java |
| 22 | + |
| 23 | +<AuthorAvatar |
| 24 | + author_name="Ellie Popoca" |
| 25 | + author_avatar="/images/projects/authors/ellie-popoca.jpg" |
| 26 | + username="ellie" |
| 27 | + uid={true} |
| 28 | +/> |
| 29 | + |
| 30 | +<BannerImage |
| 31 | + link="https://raw.githubusercontent.com/codedex-io/projects/main/projects/create-a-caesar-cipher-with-java/header.gif" |
| 32 | + description="Banner" |
| 33 | + uid={true} |
| 34 | +/> |
| 35 | + |
| 36 | +**Prerequisites**: Java fundamentals |
| 37 | +**Read Time**: 30 minutes |
| 38 | + |
| 39 | +## Introduction |
| 40 | + |
| 41 | +```terminal |
| 42 | +Wms fytc y jckmlybc kmsrf! |
| 43 | +``` |
| 44 | + |
| 45 | +Consider this chat message you just received... Only you can't because we're unable to read it. 🫠 |
| 46 | + |
| 47 | +The text above contains an _encrypted_ message, and more specifically, a Caesar Cipher! A **Caesar Cipher** is one of the oldest ways to encrypt messages. It _substitutes_ each letter using plain text by shifting it a number of places up or down the alphabet. |
| 48 | + |
| 49 | +For example, let's say we shift the letters by 3: |
| 50 | + |
| 51 | +```terminal |
| 52 | +A → D |
| 53 | +B → E |
| 54 | +C → F |
| 55 | +... |
| 56 | +X → A |
| 57 | +Y → B |
| 58 | +Z → C |
| 59 | +``` |
| 60 | + |
| 61 | +If we were to encrypt "secret password", we would get `dhfjdjt laffghrf`. Which, very conveniently, looks like keyboard smash. |
| 62 | + |
| 63 | +Let's build a program that lets you create your own cipher! |
| 64 | + |
| 65 | +<ImageZoom src="https://i.imgur.com/b6GsaQX.gif" /> |
| 66 | + |
| 67 | + |
| 68 | +## Setup |
| 69 | +Before we begin, be sure to use the correct import for the `Scanner`, since we will be utilizing user input. |
| 70 | + |
| 71 | +```java |
| 72 | +import java.util.Scanner; |
| 73 | +``` |
| 74 | + |
| 75 | +We're going to start with creating our `encrypt()` method. This method will just serve the purpose of encrypting your text (and shifting each character). |
| 76 | + |
| 77 | +This method will take two inputs, your text _and_ your shift key (or the # of spaces we're moving letters). |
| 78 | + |
| 79 | +```java |
| 80 | +public String encrypt(String text, int shift) { |
| 81 | + // Ok we're ready... |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +Next, we're going to create a `StringBuilder` object. Just as the name suggests, [StringBuilder](https://docs.oracle.com/javase/tutorial/java/data/buffers.html) is just like a String, but it can be changed using methods |
| 86 | + |
| 87 | +```java |
| 88 | +StringBuilder result = new StringBuilder(); |
| 89 | +``` |
| 90 | + |
| 91 | +## Text input iteration |
| 92 | + |
| 93 | +Now, we need to loop through each letter in our text because we want to individually tackle these letters in our user-inputted phrase since we're trying to change each letter completely. To do so, we can use an enhanced for loop called a `for`-`each` loop. |
| 94 | + |
| 95 | +Consider the sentence: "For each character in this sentence we want to do x". We can translate this text to code by writing the following: |
| 96 | + |
| 97 | +```java |
| 98 | +// for-each loop |
| 99 | +for (char character : text.toCharArray()) {} |
| 100 | +``` |
| 101 | + |
| 102 | +Which is exactly the same as doing: |
| 103 | +```java |
| 104 | +// for loop |
| 105 | +char[] chars = text.toCharArray(); |
| 106 | + |
| 107 | +for (int i = 0; i < chars.length; i++) { |
| 108 | + char character = chars[i]; |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +We are using the `.toCharArray()` method to turn our user's text into a char array to loop through it. This is what you would have if the value of `text` was "hello": |
| 113 | + |
| 114 | +```terminal |
| 115 | +['h', 'e', 'l', 'l', 'o']; |
| 116 | +``` |
| 117 | + |
| 118 | +Now that we can access each letter with the `character` variable, let's dive deeper! |
| 119 | + |
| 120 | +We only want to run the `encrypt()` method if the letters are actually letters (we can't encrypt signs like `$` or `#`). Lucky for you, there's the handy `.isLetter()` method that returns a boolean if a character is a letter. |
| 121 | + |
| 122 | +If our character is a letter, let's also handle uppercase and lowercase. We can encrypt in both cases. |
| 123 | + |
| 124 | +```java |
| 125 | +for (char character : text.toCharArray()) { |
| 126 | + if (Character.isLetter(character)) { |
| 127 | + // char base = Character.isLowerCase(character) ? 'a' : 'A'; |
| 128 | + } |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +If we take a closer look at this line, we can see that a char variable `base` is declared and initialized based on an `if`/`else`. |
| 133 | + |
| 134 | +```java |
| 135 | +char base = Character.isLowerCase(character) ? 'a' : 'A'; |
| 136 | +``` |
| 137 | + |
| 138 | +This `if`/`else` shorthand (`?` `:`) called the ternary operator provides either the `a` or `A` character depending if the letter is upper case or lower case. |
| 139 | + |
| 140 | +```terminal |
| 141 | +condition ? valueIfTrue : valueIfFalse |
| 142 | +``` |
| 143 | + |
| 144 | +## Cipher logic |
| 145 | + |
| 146 | +Currently, our `encrypt()` method should look like the following: |
| 147 | + |
| 148 | +```java |
| 149 | +public static String encrypt(String text, int shift) { |
| 150 | + StringBuilder result = new StringBuilder(); |
| 151 | + |
| 152 | + for (char character : text.toCharArray()) { |
| 153 | + if (Character.isLetter(character)) { |
| 154 | + char base = Character.isLowerCase(character) ? 'a' : 'A'; |
| 155 | + } |
| 156 | + } |
| 157 | +} |
| 158 | +``` |
| 159 | + |
| 160 | +So far, our program sets a `base` character to handle uppercase and lowercase letters if the character is a letter. We need to now handle the shift! |
| 161 | + |
| 162 | +We need to create a formula that shifts a character forward by a certain number of letters (defined by shift) and wraps around the alphabet when needed. |
| 163 | + |
| 164 | +Let's say we are trying to shift `C` 3 spaces. Since 'C' is uppercase, the base is 'A'. Characters are actually just numerical ASCII codes. `A` is 65 and `C` is 67. |
| 165 | + |
| 166 | +If we subtract the base from the character, we get: |
| 167 | + |
| 168 | +```terminal |
| 169 | +character - base = 'C' - 'A' = 67 - 65 = 2 |
| 170 | +``` |
| 171 | +So 'C' is the 2nd letter in the alphabet (index 2, starting from 0). Now we have the index of our letter, but since we're trying to shift it 3 spaces, let's add `3` to the current index. |
| 172 | + |
| 173 | +```terminal |
| 174 | +(character - base + shift) |
| 175 | +``` |
| 176 | + |
| 177 | +Let's also make sure that it _wraps_ around the alphabet, so `Z` shifted 3 spaces makes it to `C`. We can use the `%` modulo. |
| 178 | + |
| 179 | +```terminal |
| 180 | +(character - base + shift) % 26 |
| 181 | +``` |
| 182 | + |
| 183 | +Since we have a new index now, we can add our base to turn it _back_ to an ASCII value to turn it into a new letter! |
| 184 | + |
| 185 | +```terminal |
| 186 | +(character - base + shift) % 26 + base |
| 187 | +(67 - 65 + 3) % 26 + 3 = 70 |
| 188 | +``` |
| 189 | + |
| 190 | +Currently, the number 70 doesn't mean anything to us. We need to turn `70` (the integer) into `'70'` to signify the `char` 70. We can use a process called type casting, which converts different data types from one to another and this will help us store and display the shifted character, not its numeric code. |
| 191 | + |
| 192 | +We can do so by declaring a `char` variable called `shifted`, and using `(char)` to type cast: |
| 193 | + |
| 194 | +```java |
| 195 | +char shifted = (char) ((character - base + shift) % 26 + base); |
| 196 | +``` |
| 197 | + |
| 198 | +This is the formula that will shift your letters to display new ones, and encrypt your messages! |
| 199 | + |
| 200 | +Now, we need to add each letter to a string that holds our new message. This is where we can use the `.append()` method to add each letter to our `StringBuilder` object called `result`. |
| 201 | + |
| 202 | +Since we're still inside the for loop, we're adding every single character our text contains. |
| 203 | + |
| 204 | +```java |
| 205 | +result.append(shifted); |
| 206 | +``` |
| 207 | + |
| 208 | +Now, this is all under the `if` condition which checks if our character is a letter. If it is not a letter, we're going to not handle it in our encryption, and instead, add it to our `result` string so that the punctuation stays the same. |
| 209 | + |
| 210 | +Then, be sure to `return` the final string result. Your method should now look like this: |
| 211 | + |
| 212 | +```java |
| 213 | +public static String encrypt(String text, int shift) { |
| 214 | + StringBuilder result = new StringBuilder(); |
| 215 | + |
| 216 | + for (char character : text.toCharArray()) { |
| 217 | + if (Character.isLetter(character)) { |
| 218 | + char base = Character.isLowerCase(character) ? 'a' : 'A'; |
| 219 | + char shifted = (char) ((character - base + shift) % 26 + base); |
| 220 | + result.append(shifted); |
| 221 | + } else { |
| 222 | + result.append(character); |
| 223 | + } |
| 224 | + } |
| 225 | + |
| 226 | + return result.toString(); |
| 227 | +} |
| 228 | +``` |
| 229 | + |
| 230 | + |
| 231 | +## Handling User Input |
| 232 | + |
| 233 | +For this last part, we need to use the `Scanner` to handle user input and wrap up our Caesar Cipher encrypter. |
| 234 | + |
| 235 | +You'll need two things from the user: |
| 236 | +- text to encrypt (String) |
| 237 | +- the shift number (0-25) (int) |
| 238 | + |
| 239 | +```terminal |
| 240 | +Enter text to encrypt: Thank you Penguin123 for keeping Club Penguin safe. Here are four hundred coins. |
| 241 | +Enter shift key (0-25): 17 |
| 242 | +``` |
| 243 | + |
| 244 | +Declare and initialize the `Scanner` object, and allow users to provide text and a shift key. |
| 245 | + |
| 246 | +```java |
| 247 | +public static void main(String[] args) { |
| 248 | + Scanner scanner = new Scanner(System.in); |
| 249 | + |
| 250 | + System.out.print("Enter text to encrypt: "); |
| 251 | + String inputText = scanner.nextLine(); |
| 252 | + |
| 253 | + System.out.print("Enter shift key (0-25): "); |
| 254 | + int shiftKey = scanner.nextInt(); |
| 255 | + |
| 256 | + String encrypted = encrypt(inputText, shiftKey); |
| 257 | + System.out.println("Encrypted text: " + encrypted); |
| 258 | +} |
| 259 | +``` |
| 260 | + |
| 261 | +Your project is now ready to be tested, try encrypting your favorite movie quote if you'd like! |
| 262 | + |
| 263 | +## Conclusion |
| 264 | + |
| 265 | +Congratulations!!! 🎊 |
| 266 | + |
| 267 | +You've reached the end of the project, and now you have a cool encrypter to mess around with! |
| 268 | + |
| 269 | +<ImageZoom src="https://i.imgur.com/IYCu7c4.gif" /> |
| 270 | + |
| 271 | +However, there are always more features you can add to your cipher! |
| 272 | + |
| 273 | +Some other ideas include: |
| 274 | + |
| 275 | +- Adding a "decrypt" method, and figuring out how to get your original message back |
| 276 | +- Decrypting a message that outputs every 25 shifts to quickly find your original message |
| 277 | +- Add command line flags like `-e` or `-d` to quickly encrypt or decrypt |
| 278 | +- Figure out how to guess the key based on letter frequency (e.g. 'E' is common). |
| 279 | + |
| 280 | +Share your projects with the team [@codedex_io](https://www.twitter.com/codedex_io) and me, [@exrlla](https://www.twitter.com/exrlla)! Let us know what you come up with, and what encrypted messages you'd like to send! ✨ |
0 commit comments