From 7d8f778404d2c509c0c5f04b2760868fd39015c7 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Thu, 15 May 2025 09:03:06 -0700 Subject: [PATCH 1/7] Rewrite the Simple Cipher description. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See [forum discussion](https://forum.exercism.org/t/simple-cipher-change-proposal-rewrite-the-description/17380] Key improvements: * Remove mentions of "Steps" and "Extension". * Replace "Caeser cipher" with "Vigenère cipher" to accurately match what is being asked. * Use a format in line with the other cipher exercises. --- exercises/simple-cipher/description.md | 76 ++++++++------------------ 1 file changed, 24 insertions(+), 52 deletions(-) diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index 6232b60d92..04b36593ca 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -1,66 +1,38 @@ # Description -Implement a simple shift cipher like Caesar and a more secure substitution cipher. +Create an implementation the [Vigenère cipher][wiki]. +The Vigenère cipher is simple substitution cipher. -## Step 1 +## Cipher terminology -"If he had anything confidential to say, he wrote it in cipher, that is, by so changing the order of the letters of the alphabet, that not a word could be made out. -If anyone wishes to decipher these, and get at their meaning, he must substitute the fourth letter of the alphabet, namely D, for A, and so with the others." -—Suetonius, Life of Julius Caesar +A cipher is an algorithm used to encrypt, or encode, a string. +The unencrypted string is called the _plaintext_ and the encrypted string is called the _ciphertext_. +Converting plaintext to ciphertext is called _encoding_ while the reverse is called _decoding_. -Ciphers are very straight-forward algorithms that allow us to render text less readable while still allowing easy deciphering. -They are vulnerable to many forms of cryptanalysis, but Caesar was lucky that his enemies were not cryptanalysts. +In a _substitution cipher_, each letter is replaced with a different letter which is computed with the help of a _key_. -The Caesar cipher was used for some messages from Julius Caesar that were sent afield. -Now Caesar knew that the cipher wasn't very good, but he had one ally in that respect: almost nobody could read well. -So even being a couple letters off was sufficient so that people couldn't recognize the few words that they did know. +## Encoding details -Your task is to create a simple shift cipher like the Caesar cipher. -This image is a great example of the Caesar cipher: +In this cipher, the key is a series of lowercase letters, such as `"abcd"`. +Each letter of the plaintext is _shifted_ or _rotated_ by a distance based on a corresponding letter in the key. +An `"a"` in the key means a shift of 0 (that is, no shift). +A `"b"` in the key means a shift of 1. +A `"c"` in the key means a shift of 2, and so on. -![Caesar cipher][img-caesar-cipher] +The first letter of the plaintext uses the first letter of the key, the second letter of the plaintext uses the second letter of the key and so on. +If you run out of letters in the key before you run out of letters in the plaintext, start over from the start of the key again. -For example: +If the key only contains one letter, such as `"dddddd"`, then all letters of the plaintext are shifted by the same amount (three in this example), which would make this the same as a rotational cipher or shift cipher (sometimes called a Caesar cipher). +For example, the plaintext `"iamapandabear"` would become `"ldpdsdqgdehdu"`. -Giving "iamapandabear" as input to the encode function returns the cipher "ldpdsdqgdehdu". -Obscure enough to keep our message secret in transit. +If the key only contains the letter `"a"` (one or more times), the shift distance is zero and the ciphertext is the same as the plaintext. -When "ldpdsdqgdehdu" is put into the decode function it would return the original "iamapandabear" letting your friend read your original message. +Usually the key is more complicated than that, though! +If the key is `"abcd"` then letters of the plaintext would be shifted by a distance of 0, 1, 2 then 3. +Using that key, `"hello"` would become `"hfnoo"`. -## Step 2 +## Random keys -Shift ciphers quickly cease to be useful when the opposition commander figures them out. -So instead, let's try using a substitution cipher. -Try amending the code to allow us to specify a key and use that for the shift distance. +If no key is provided, generate a key which consists of at least 100 random lowercase letters from the Latin alphabet. -Here's an example: - -Given the key "aaaaaaaaaaaaaaaaaa", encoding the string "iamapandabear" -would return the original "iamapandabear". - -Given the key "ddddddddddddddddd", encoding our string "iamapandabear" -would return the obscured "ldpdsdqgdehdu" - -In the example above, we've set a = 0 for the key value. -So when the plaintext is added to the key, we end up with the same message coming out. -So "aaaa" is not an ideal key. -But if we set the key to "dddd", we would get the same thing as the Caesar cipher. - -## Step 3 - -The weakest link in any cipher is the human being. -Let's make your substitution cipher a little more fault tolerant by providing a source of randomness and ensuring that the key contains only lowercase letters. - -If someone doesn't submit a key at all, generate a truly random key of at least 100 lowercase characters in length. - -## Extensions - -Shift ciphers work by making the text slightly odd, but are vulnerable to frequency analysis. -Substitution ciphers help that, but are still very vulnerable when the key is short or if spaces are preserved. -Later on you'll see one solution to this problem in the exercise "crypto-square". - -If you want to go farther in this field, the questions begin to be about how we can exchange keys in a secure way. -Take a look at [Diffie-Hellman on Wikipedia][dh] for one of the first implementations of this scheme. - -[img-caesar-cipher]: https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Caesar_cipher_left_shift_of_3.svg/320px-Caesar_cipher_left_shift_of_3.svg.png -[dh]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange +[wiki]: https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher From a9329ac2ba252077d0c0acf4f7d19140d93cffd5 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Thu, 15 May 2025 09:12:25 -0700 Subject: [PATCH 2/7] Fix a type: `s/is/is a/` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: András B Nagy <20251272+BNAndras@users.noreply.github.com> --- exercises/simple-cipher/description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index 04b36593ca..a8a18f8d12 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -1,7 +1,7 @@ # Description Create an implementation the [Vigenère cipher][wiki]. -The Vigenère cipher is simple substitution cipher. +The Vigenère cipher is a simple substitution cipher. ## Cipher terminology From 44486e1326225f4436fc878a29bf5584c095fb6c Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Thu, 15 May 2025 10:45:03 -0700 Subject: [PATCH 3/7] Fix typo in exercises/simple-cipher/description.md: s/implementation the/implementation of the/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: András B Nagy <20251272+BNAndras@users.noreply.github.com> --- exercises/simple-cipher/description.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index a8a18f8d12..86c8ada6c9 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -1,6 +1,6 @@ # Description -Create an implementation the [Vigenère cipher][wiki]. +Create an implementation of the [Vigenère cipher][wiki]. The Vigenère cipher is a simple substitution cipher. ## Cipher terminology From 2988301d684a85bae1dc989de6d15d6d85b74e1b Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Thu, 15 May 2025 16:02:01 -0700 Subject: [PATCH 4/7] Mention that the replacement letter can match the original letter. --- exercises/simple-cipher/description.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index 86c8ada6c9..30e4aecb61 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -9,7 +9,9 @@ A cipher is an algorithm used to encrypt, or encode, a string. The unencrypted string is called the _plaintext_ and the encrypted string is called the _ciphertext_. Converting plaintext to ciphertext is called _encoding_ while the reverse is called _decoding_. -In a _substitution cipher_, each letter is replaced with a different letter which is computed with the help of a _key_. +In a _substitution cipher_, each plaintext letter is replaced with a ciphertext letter which is computed with the help of a _key_. +(Note, it is possible for replacement letter to be the same as the original letter! +As mentioned earlier, an `"a"` in the key means there is no shift/change.) ## Encoding details From 116343a752926a166f089002a766764610052478 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Thu, 15 May 2025 21:33:08 -0700 Subject: [PATCH 5/7] =?UTF-8?q?Update=20the=20metadata=20blurb=20to=20swap?= =?UTF-8?q?=20Caeser=20for=20Vigen=C3=A8re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exercises/simple-cipher/metadata.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/simple-cipher/metadata.toml b/exercises/simple-cipher/metadata.toml index daccfac045..590d4c8c9c 100644 --- a/exercises/simple-cipher/metadata.toml +++ b/exercises/simple-cipher/metadata.toml @@ -1,4 +1,4 @@ title = "Simple Cipher" -blurb = "Implement a simple shift cipher like Caesar and a more secure substitution cipher." +blurb = "Implement the Vigenère cipher, a simple substitution cipher." source = "Substitution Cipher at Wikipedia" source_url = "https://en.wikipedia.org/wiki/Substitution_cipher" From d7332e0071fee9723e583ede7ad313240b025525 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Fri, 16 May 2025 08:33:10 -0700 Subject: [PATCH 6/7] Drop the "earlier" reference --- exercises/simple-cipher/description.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index 30e4aecb61..5539202e68 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -10,8 +10,7 @@ The unencrypted string is called the _plaintext_ and the encrypted string is cal Converting plaintext to ciphertext is called _encoding_ while the reverse is called _decoding_. In a _substitution cipher_, each plaintext letter is replaced with a ciphertext letter which is computed with the help of a _key_. -(Note, it is possible for replacement letter to be the same as the original letter! -As mentioned earlier, an `"a"` in the key means there is no shift/change.) +(Note, it is possible for replacement letter to be the same as the original letter.) ## Encoding details From 6ce9036ef2b78dc3c88db0ec997dd83f1e361110 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Sat, 17 May 2025 10:59:09 -0700 Subject: [PATCH 7/7] Add more details to the hello example --- exercises/simple-cipher/description.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index 5539202e68..950953bfa8 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -29,8 +29,9 @@ For example, the plaintext `"iamapandabear"` would become `"ldpdsdqgdehdu"`. If the key only contains the letter `"a"` (one or more times), the shift distance is zero and the ciphertext is the same as the plaintext. Usually the key is more complicated than that, though! -If the key is `"abcd"` then letters of the plaintext would be shifted by a distance of 0, 1, 2 then 3. -Using that key, `"hello"` would become `"hfnoo"`. +If the key is `"abcd"` then letters of the plaintext would be shifted by a distance of 0, 1, 2, and 3. +If the plaintext is `"hello"`, we need 5 shifts so the key would wrap around, giving shift distances of 0, 1, 2, 3, and 0. +Applying those shifts to the letters of `"hello"` we get `"hfnoo"`. ## Random keys