We are going to make a simple program which will encrypt our data using Caesar cipher
What is the Caesar Cipher?
The Caesar cipher is a type of substitution cipher which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. The number of fixed positions down the alphabet is what we call the key. It was named after Julius Caesar since he was the one who invented it.
How It Works
So as I said earlier on, each letter during encryption is moved some fixed positions down the alphabet. So for a key of 3, if we are to encipher the letter A, we will shift it down three characters and the results will be D, C would be F and so on...
To decipher or decrypt, it will be the reverse process, we will count the letters backwards and the number of times will be determined by the key. So in order to decipher A with a key of 5, we will count 5 letters backwards and we will get V.
Writing the algorithm in Ruby
Since am learning Ruby, I decided it was the best language to use since it will help me understand it more, and besides, Ruby is a very easy and simple language to understand. Also, we are going to use object oriented approach since that will make everything easier for us and it's the best way too.
class Caesar
@@UPPERCASE_LETTERS = ("A".."Z").to_a #Uses the range to create the uppercase letters and converts it to an array
@@LOWERCASE_LETTERS = ("a".."z").to_a #Uses the range to create the lowercase letters and converts it to an array
attr_accessor :key #This allows us to get and set the key without creating methods
def initialize(key)
#The constructor recieves the key on initialization
@key = key #The key is then made an instance variable which makes it accessible
end
def encrypt(text)
#This method handles the encryption of the text
encrypted = "" #This is the variable which will hold the encrypted text
text.split("").to_a.each do |x| #Converts the text into an array an iterate over each index
if @@UPPERCASE_LETTERS.include? x #We then check if the current variable is included in the UPPERCASE array
encrypted += @@UPPERCASE_LETTERS[ (@@UPPERCASE_LETTERS.index(x) + key) % 26] #We then find it's index and add the key to it
elsif @@LOWERCASE_LETTERS.include? x
encrypted += @@LOWERCASE_LETTERS[ (@@LOWERCASE_LETTERS.index(x) + key) % 26]
else
encrypted += x
end
end
return encrypted
end
def decrypt(text)
#This method is responsible for decrypting the encrypted text
decrypted = "" #This variable will hold the decrypted text
text.split("").to_a.each do |x|
if @@UPPERCASE_LETTERS.include? x
decrypted += @@UPPERCASE_LETTERS[ (@@UPPERCASE_LETTERS.index(x) - key) % 26]
elsif @@LOWERCASE_LETTERS.include? x
decrypted += @@LOWERCASE_LETTERS[ (@@LOWERCASE_LETTERS.index(x) - key) % 26]
else
decrypted += x
end
end
return decrypted
end
end
The code above is the Caesar cipher in Ruby. So let me explain parts of the code. The encrypt and decrypt method is similar so the explanation is the same for all.
The method receives text as it's argument
It then converts the text into an array and iterates over each character,
-
In each iteration:
- We check if the character is included in either of the
@@LOWERCASE_LETTERS
or@@UPPERCASE_LETTERS
array with the use of the.include?
method which takes the character as the argument - Then, we try to find the index of the character using
array.index(character)
, this will return the numerical index of the letter in the array. - Depending on whether we are encrypting or decrypting, we will add or subtract respectively.
Now, since when we add the key, it will make the array much larger than it's length, we need to find the modular 26 (length of the array) of the
(array.index(character) + key)
, this will make sure the number which we will receive is less than the length of the array. - We then use the number we received as an index to fetch the encrypted character
- We check if the character is included in either of the
Using The Cipher
So in order to use the class we just created, we need to create an instance of it.
Remember the class takes the key as the constructor
cipher = Caesar.new(5)
puts cipher.encrypt("Sentence") #=>Pbkqbkzb
puts cipher.decrypt("Pbkqbkzb") #=> Sentence
Happy Coding😆
Top comments (3)
if @@UPPERCASE_LETTERS.include? x
can be replaced with:
if x.match?(/[A-Z]/)
and the other conditional could be:
if x.match?(/[a-z]/)
the formula to find the appropriate replacement is interesting. Doesn't have to use
.ord
and.chr
that's right, if you have to cipher words, instead of
split
you can usechars
that also changes the word to an array, or useeach_char
to pass each character to a block.It is a nice option, check the documentation for info: ruby-doc.org/core-3.1.2/String.html
Asking/showing your answer in Ruby channel in Discord helps too. Helped me realize I have a long way to go... still, the fun is walking that path. =D
Keep on rocking!
Nice implementation of Caesar cipher.
Let me ask one question, is it necessary to use
to_a
method, becausesplit
itself returns an array of characters?I just realized😅, it isn't necessary