Caesar Cipher
Most of us like to keep secrets. For example, I don't want you to know my credit card number. I'd rather you not be able to buy things with my money. However, communication over the Internet is like trying to shout in a crowded room. Everyone can hear what you are saying. So, to protect our valuable secrets, we rely on encryption schemes. Today, you are going to implement a simplistic encryption scheme known since Roman times: Caesar cipher.
Encryption in the Caesar schema relies on shifting letters in the alphabet. By default, this shift is 3 letters. So, a becomes d, b becomes e, etc. The only issue with this is at the end of the alphabet. The end of the alphabet wraps around to the front. So, x becomes a, y becomes b, and z becomes c.
Details
Create the function encode_caesar(plaintext: str) ->
str
that encodes text using the Caesar cipher. The
parameter plaintext is a string of lowercase characters.
The function should return a string of lowercase characters, which
is equivalent to the plaintext with each character shifted by 3.
Test Cases
import test def encode_caesar(plaintext: str) -> str: # Put your code here def main() -> None: test.equal(encode_caesar("hello"), "khoor") # Put more test cases here return None main()
-
The
ord
function gives you the numeric representation of a character. Subtract theord('a')
from this, to get the position in alphabet a character is. - Use addition to shift the numeric representation of the character.
-
The numeric representation may be too large after the shift.
You can use the
%
operator to wrap the number around to the beginning. - Finally, use the
chr
function to convert the numeric value back to a character.
Challenge
Encryption for Caesar is useful, but in order to talk to anyone they
need to be able to decrypt the Caesar encryption. Write the
function decode_caesar(ciphertext: str) -> str
that
decrypts the ciphertext.
Substitution Cipher
Another common technique for encryption is known as the Substitution Cipher. Instead of defining a linear equation between the plaintext and ciphertext, you can define a map that translates characters using a specified order. Crypograms use this technique, for example.
The key in the substitution cipher is a string of characters in the
range [a, z]. For example, the
string "abcdefghijklmnopqrstuvwxyz"
is one possible key
in the substitution cipher. It maps the letter 'a' to the letter
'a', the letter 'b' to 'b', and so on. A more interesting example
would be "zyxwvutsrqponmlkjihgfedcba", which maps 'a' to 'z', 'b' to
'y', and so on. For example, "hello world" would become "svool
dliow" under this key.
Details
Create the function encode_substitution(plaintext: str, key:
str) -> str
that encodes text using the substitution cipher.
The parameter plaintext is a string of lowercase characters
and the parameter key is a string that contains all of the
letters of the alphabet, in lowercase, in any order. The funciton
should return a string of lowercase characters, which is equivalent
to the plaintext with each character substituted with its
corresponding letter.
Test Cases
import test def encode_substitution(plaintext: str, key: str) -> str: # Put your code here def main() -> None: test.equal(encode_substitution("hello", "zyxwvutsrqponmlkjihgfedcba"), "svool") # Put more test cases here return None main()
- Given a character, compute its index in the alphabet. This is the same as converting a number into the range 0 - 25 before shifting in the caesar cipher.
- Use the index of the character to get the character at the same index in the key string. This is the encrypted value of the character.
- Return the accumulated encrypted characters.
Challenge
Write the function decode_substitution(ciphertext: str, key:
str) -> str
that decrypts the ciphertext with the
associated key.
Vigenere Cipher
Cryptography is the science of hiding secrets. A typical cryptographic protocol takes some plaintext message and some key, and produces a ciphertext that is unreadable by anyone that does not know the key.
We observed a very simplistic encryption scheme: Caesar cipher. This encryption scheme has been in use since Roman times, and is very easily breakable. As such, we likely want a stronger encryption scheme to make our messages even more secure.
The key in caesar is 3. To encrypt, you chose the letter 3 spaces further in the alphabet of the entered character. In Vigenere, the key is a word. For each character in the plaintext, you use the corresponding letter in the key to determine how much to shift that character by.
Consider the plaintext "hello", with a key of "hi". This means to encrypt the "h" in hello, you use the letter "h" as the shift (Which is a shift of 7, since h is the 7th character of the alphabet). Then, for the letter "e" in hello, you would use the letter "i" as the shift (which is a shift of 8). But, now we have run out of letters in the key. In this case, you wrap back around to the beginning of the key string, using "h" as the key for the first "l" in hello.
Details
Create the function encode_vigenere(plaintext: str, key: str)
-> str
that encodes text using the vigenere cipher. Both
parameters plaintext and key are strings of
lowercase characters. The function should return a string of
lowercase characters, which is equivalent to the plaintext with each
character shifted according to the key.
Test Cases
import test def encode_vigenere(plaintext: str, key: str) -> str: # Put your code here def main() -> None: test.equal(encode_vigenere("hello", "hi"), "omstv") # Put more test cases here return None main()
- The actual encryption of this will be very similar to the caesar cipher, with a change to the shift that occurs.
- Instead of always shifting by 3. Convert the current character in the key, to a shift ammount. Do this the same way you convert a plaintext character to a number from 0 to 25 before shifting it.
-
In order to account for the wrapping around of the key, use
the
%
operator. You will likely want to mod by the length of your key.
Challenge
The vigenere cipher is possibly the strongest classical cipher you
will encounter. Which means that writing a decryption function is
of the utmost importance. Write the function
decode_vigenere(ciphertext: str, key: str) -> str
that
decrypts the ciphertext with the associated key.