The Vigenère cipher is a simple substitution cipher. It is a more complex cipher than the Caesar cipher and encrypting a message using the Vigenère cipher is also more secure when compared to that using the Caesar cipher. The Vigenère cipher, just like the Caesar cipher, belongs to a specific subset of encryption scheme called the
substitution ciphers.
The Vigenère cipher is a
polyalphabetic cipher from the 16th century which uses several Caesar ciphers to encrypt the same message that renders more complexity to the whole encryption scheme/process, thereby making the cipher hard to crack. The ‘polyalphabetic cipher’ kind of encryption scheme is believed to have been developed by the Arabic mathematicians as early as 800 CE ("Common Era" or "Christian Era"), was used for military purposes and relied upon by the Confederates in the American Civil War.
First documented in 1553, the Vigenère cipher is thought to have remained unbroken until 1863. The Vigenère cipher was often referred to as “the unbreakable cipher” by many, including the mathematician Charles Lutwidge Dodgson, also known by his pen name Lewis Carroll. The Vigenère cipher had been used by the British spies in the Second World War – they used to use the first lines of poems as keys in their Vigenère ciphers and this often made it easy for the enemies to guess the ciphertext messages.
The Vigenère cipher encryption system/scheme is symmetric and therefore, both the sender and receiver of the message should know how the message has been encrypted and ensure that the information is kept secret from any unwanted third person.
Vigenère cipher Key Generation
The Vigenère cipher key is a string of letters. The longer and more random the Vigenère cipher key is, the harder will it be to break the encryption.
Vigenère SquareA Vigenère square is a grid or matrix formed by writing the alphabets repeatedly, starting at different places. The following figure depicts a Vigenère square.
Vigenère cipher Encryption Process
Encrypting a plaintext message using the Vigenère cipher requires the Vigenère cipher key and Vigenère square.
In order to encrypt a plaintext message using the Vigenère cipher, each letter in the message is replaced with a cipher letter which is chosen by finding the intersection of the correct row and column. In order to choose the correct row, we should find in the first column of the Vigenère square the letter present in the plaintext message. For example, if the plaintext message was ‘PYTHON’, the first letter ‘P’ of the plaintext message would be encrypted using the row in the Vigenère square beginning with the letter “P”.
In order to choose the correct column, we need the Vigenère cipher key. For the first letter present in the plaintext message, we should choose that column in the Vigenère square that starts with the first letter in the key; for the second letter present in the plaintext message, we should choose the column in the Vigenère square that starts with the second letter in the key, and so on. For example, let us assume that the Vigenère cipher key is ‘CAT’. The first letter present in the plaintext message would be encrypted using the column in the Vigenère square that begins with the letter ‘C’; the second letter present in the plaintext message would be encrypted using the column in the Vigenère square that begins with the letter ‘A’ and the third letter present in the plaintext message would be encrypted using the column in the Vigenère square that begins with the letter ‘T’. If the plaintext message is longer than the Vigenère cipher key, we should wrap back in the key and reuse the letters of the key in order.
Vigenère cipher Encryption Example
Let us assume that the Vigenère cipher key is DOG and the plaintext message is LOAD.
Vigenère cipher Decryption Process
Decrypting a ciphertext message back to the original plaintext message requires the reversal of the encryption process. In the decryption process, we first find the row that corresponds to the nth letter in the Vigenère cipher key. We then keep looking along that row until we find the nth letter in the ciphertext. The letter present at the top of the column in the Vigenère square is the plaintext letter.
Let us consider the ciphertext ‘OCGG’ and the Vigenère cipher key ‘DOG’. In order to decrypt the ciphertext message back to the original plaintext message, we start at the row ‘D’ in the Vigenère square and look for the position of the letter “O” in the row. The letter present at the top of the column is ‘L’, which is the first letter of the original plaintext message.
How easy or difficult is it to break the Vigenère cipher?
It should be noted here that we can employ a variety of techniques in order to decrypt a Caesar cipher and we don’t even need to know about the Caesar cipher key. That is because the patterns in the plaintext message get preserved by the Caesar cipher encryption scheme. However, when compared with the Caesar cipher, it is more complex to break the Vigenère cipher.
In the Vigenère cipher, the number of places a letter in the plaintext message is shifted in the alphabet changes for each letter in the plaintext message. This, in turn, means that the most frequently used letters in the ciphertext do not correspond to the most frequently used letters in the plaintext. Moreover, if we find a letter used more than once consecutively in the ciphertext, that doesn’t mean that the consecutively used letter in the ciphertext correspond to a consecutively used letter in those positions in the plaintext. As a result of these features, it took a lot longer to break the Vigenère cipher than it took to break the Caesar cipher.
However, having said all these, the Vigenère cipher is not unbreakable at all. For example, spies used the lines of famous poems as their Vigenère cipher keys in the Second World War. German codebreakers had figured out the pattern and it then became easier for them to guess a ciphertext’s encryption key and eventually decrypt the message. It is a matter of common sense that being able to guess the key that was used to encrypt a plaintext message will mean that the ciphertext message can be decrypted back to the original plaintext message.
> Patterns in the ciphertext can still provide some clues. It is very likely that a sequence of letters repeated in multiple places in the ciphertext message could be the same word (or part of a word) of the plaintext message encrypted using the same part of the key. It is quite less likely (could happen, but very less likelihood of happening) that such repetitions in the ciphertext message are different sets of letters in the plaintext message that were encrypted as the same pattern in the ciphertext message.
> Codebreakers could use a technique called ‘dragging’ to crack the Vigenère cipher. Suppose that the codebreaker thinks that he/she may know about a word or phrase that will be in the plaintext message. The codebreaker can then test to see if his/her guessed word or phrase has been encrypted anywhere in the message until the time that such a process produces a key that appears not to be random. When the codebreaker has a clue to the key, he/she can then try decrypting the rest of the ciphertext message. By doing that, the codebreaker will have an idea if he/she has been able to discover the whole key - if not, the codebreaker has to try multiple approaches which is usual with the ‘dragging’ process, until enough patterns in the message, that can help in decrypting the ciphertext message back to the original plaintext message, can be spotted.
The GIF image embedded below demonstrates the ‘dragging’ process or technique explained above.
So, by now, it is quite evident that decryption of the ciphertext message back to the original plaintext message for the Vigenère cipher requires more deduction and guesswork than in the Caesar cipher.
Implementation of the Vigenère cipher in the Python Programming Language
def new_alphabet(key_character):
key_character = key_character.lower()
alphabet = 'abcdefghijklmnopqrstuvwxyz'
new_alphabet = alphabet[alphabet.index(key_character):] + alphabet[:alphabet.index(key_character)]
return new_alphabet
def encryption(plaintext, cipher_key):
encryption_result = ''
alphabet = 'abcdefghijklmnopqrstuvwxyz'
index = 1
for key_letter in cipher_key:
resultant_new_alphabet = new_alphabet(key_letter)
for plaintext_letter in plaintext:
if alphabet.count(plaintext_letter) == 1 :
encryption_result += resultant_new_alphabet[alphabet.index(plaintext_letter)]
plaintext = plaintext[index:]
break
elif alphabet.count(plaintext_letter.lower()) == 1:
encryption_result += resultant_new_alphabet[alphabet.index(plaintext_letter.lower())].upper()
plaintext = plaintext[index:]
break
else:
encryption_result += plaintext_letter
plaintext = plaintext[index:]
break
index += 1
return encryption_result
def decrypt(ciphertext, cipher_key):
decryption_result = ''
alphabet = 'abcdefghijklmnopqrstuvwxyz'
index = 1
for key_letter in cipher_key:
resultant_new_alphabet = new_alphabet(key_letter)
for ciphertext_letter in ciphertext:
if alphabet.count(ciphertext_letter) == 1 :
decryption_result += alphabet[resultant_new_alphabet.index(ciphertext_letter)]
ciphertext = ciphertext[index:]
break
elif alphabet.count(ciphertext_letter.lower()) == 1:
decryption_result += alphabet[resultant_new_alphabet.index(ciphertext_letter.lower())].upper()
ciphertext = ciphertext[index:]
break
else:
decryption_result += ciphertext_letter
ciphertext = ciphertext[index:]
break
index += 1
return decryption_result
plaintext_message = str(input(' Please enter the plaintext message that you want to encrypt using Vigenère cipher.'))
print(' Thank you for entering the following plaintext message.')
print(' ' + plaintext_message)
user_input_key = str(input(' Please enter the Vigenère cipher key.'))
print(' Thank you for entering the following Vigenère cipher key.')
print(' ' + user_input_key)
if len(user_input_key) <= len(plaintext_message):
vigenère_cipher_key = user_input_key * (len(plaintext_message) // len(user_input_key)) + user_input_key[:len(plaintext_message) % len(user_input_key)]
text_encryption = encryption(plaintext_message, vigenère_cipher_key)
text_decryption = decrypt(text_encryption, vigenère_cipher_key)
print(' \nEncrypting the original plaintext message using Vigenère cipher ... ')
print(' Ciphertext Message: ' + text_encryption)
print(' \nDecrypting the ciphertext message back to the original plaintext message using Vigenère cipher ... ')
print(' Original Plaintext Message: ' + text_decryption)
else:
print('Error: len(key)>len(text) ')
Please enter the plaintext message that you want to encrypt using Vigenère cipher.LOAD2$
Thank you for entering the following plaintext message.
LOAD2$
Please enter the Vigenère cipher key.DOG
Thank you for entering the following Vigenère cipher key.
DOG
Encrypting the original plaintext message using Vigenère cipher ...
Ciphertext Message: OCGG2$
Decrypting the ciphertext message back to the original plaintext message using Vigenère cipher ...
Original Plaintext Message: LOAD2$
************************************************************************************************************************************************************
The author of the technical article, Subhasish Sarkar (SS), is an IBM Z Champion for 2020.
************************************************************************************************************************************************************