DEV Community

Cover image for Understanding the Vigenère Cipher
Ayush Saha
Ayush Saha

Posted on • Originally published at cognivibes.github.io

Understanding the Vigenère Cipher

About Vigenère Cipher

The Vigenère cipher is a classic encryption technique that dates back to the 16th century. It was invented by a French diplomat and cryptographer named Blaise de Vigenère, hence the name. It was known as “le chiffre indéchiffrable,” which means “the indecipherable cipher,” and remained unbroken until British polymath Charles Babbage broke it in the 19th century.

How it works

The Vigenère cipher is a polyalphabetic substitution cipher that uses a keyword to encrypt and decrypt messages. The key idea behind the Vigenère cipher is to use multiple Caesar ciphers based on the letters of the keyword.

Hacking the Caesar Cipher | cogniVibes

Learn to encrypt or decrypt a Caesar Cipher or hack it

favicon cognivibes.github.io

Let's say we have a plaintext message PP consisting of nn letters: P=p1,p2,,pnP = p_1, p_2, \ldots, p_n ​. We also have a keyword KK consisting of mm letters: K=k1,k2,,kmK = k_1, k_2, \ldots, k_m ​, where mnm \leq n .

To encrypt the message, we repeat the keyword until it matches the length of the plaintext. Let K=k1,k2,,km,k1,k2,,km,K' = k_1, k_2, \ldots, k_m, k_1, k_2, \ldots, k_m, \ldots repeated until it matches the length of PP .

To encrypt each letter pip_i ​ in the plaintext, we find the corresponding letter kjk_j ​ in the keyword KK' where jj is the index of pip_i ​ modulo mm . Then, we shift the letter pip_i ​ by the index of kjk_j ​ in the alphabet. Let EE represent the encrypted message.

The mathematical representation of the encryption process is given by:

Ei=(pi+kj)mod26E_i = (p_i + k_j) \mod 26

where EiE_i ​ is the ii -th letter of the encrypted message and j=(i1)modmj = (i−1) \mod m .

To decrypt the message, we use a similar process. We repeat the keyword until it matches the length of the ciphertext. Let K=k1,k2,,km,k1,k2,,km,K'' = k_1, k_2, \ldots, k_m, k_1, k_2, \ldots, k_m, \ldots (repeated until it matches the length of EE ).

To decrypt each letter EiE_i ​ in the ciphertext, we find the corresponding letter kjk_j ​ in the keyword KK' (where jj is the index of EiE_i ​ modulo mm ). Then, we shift the letter EiE_i​ back by the index of kjk_j ​ in the alphabet. Let DD represent the decrypted message.

The mathematical representation of the decryption process is given by:

Di=(Eikj)mod26D_i = (Ei−kj) \mod 26

where DiD_i ​ is the ii -th letter of the decrypted message and j=(i1)modmj = (i−1) \mod m .

Note that in these equations, we use modular arithmetic with 2626 since there are 2626 letters in the English alphabet. Additionally, we assume a simple mapping where AA is represented by 00 , BB by 11 , and so on.

Example

Let's use the word "KEY" as the keyword and encrypt the plaintext message "HELLO" using the Vigenère cipher.

First, we repeat the keyword "KEY" to match the length of the plaintext "HELLO". Thus, the repeated keyword becomes "KEYKE".

The corresponding numerical representation of the plaintext message "HELLO" is:

H7E4L11L11O14H \rightarrow 7\\ E \rightarrow 4\\ L \rightarrow 11\\ L \rightarrow 11\\ O \rightarrow 14

Using the mathematical encryption formula Ei=(pi+kj)mod26E_i = (p_i+k_j) \mod 26 , we can calculate the encrypted values as follows:

E1=(7+10)mod26=17RE2=(4+4)mod26=8IE3=(11+24)mod26=9JE4=(11+10)mod26=21VE5=(14+4)mod26=18SE_1 = (7 + 10) \mod 26 = 17 \rightarrow R\\ E_2 = (4 + 4) \mod 26 = 8 \rightarrow I\\ E_3 = (11 + 24) \mod 26 = 9 \rightarrow J\\ E_4 = (11 + 10) \mod 26 = 21 \rightarrow V\\ E_5 = (14 + 4) \mod 26 = 18 \rightarrow S

Thus, the encrypted message is "RIJVS".

To decrypt the ciphertext "RIJVS" back to the original plaintext, we repeat the keyword "KEY" to match the length of the ciphertext. Thus, the repeated keyword becomes "KEYKE".

Using the mathematical decryption formula Di=(Eikj)mod26D_i=(E_i−k_j) \mod 26 , we can calculate the decrypted values as follows:

D1=(1710)mod26=7HD2=(84)mod26=4ED3=(924)mod26=11LD4=(2110)mod26=11LD5=(184)mod26=14OD_1 = (17 - 10) \mod 26 = 7 \rightarrow H\\ D_2 = (8 - 4) \mod 26 = 4 \rightarrow E\\ D_3 = (9 - 24) \mod 26 = 11 \rightarrow L\\ D_4 = (21 - 10) \mod 26 = 11 \rightarrow L\\ D_5 = (18 - 4) \mod 26 = 14 \rightarrow O

Thus, the decrypted message is "HELLO".

Vigenère Table

Encryption/decryption in case of Vigenere Cipher is a tedious task. The Vigenère table, also known as the Vigenère square or the Tabula Recta, is used to simplify the process of encryption and decryption.


Fig 1. The Vigenère Table

It consists of a grid or matrix that provides a systematic way of encrypting and decrypting messages using the Vigenère cipher. The table is formed by aligning multiple Caesar ciphers together, each with a different shift value determined by a keyword. The rows and columns of the table represent the letters of the alphabet, and each cell contains the letter resulting from combining the row and column letters using the Caesar cipher.

The Code

The encryption-decryption script can be downloaded from here:

About Vigenère Cipher

The Vigenère cipher is a classic encryption technique that dates back to the 16th century. It was invented by a French diplomat and cryptographer named Blaise de Vigenère, hence the name. It was known as “le chiffre indéchiffrable,” which means “the indecipherable cipher,” and remained unbroken until British polymath Charles Babbage broke it in the 19th century.

How it works

The Vigenère cipher is a polyalphabetic substitution cipher that uses a keyword to encrypt and decrypt messages. The key idea behind the Vigenère cipher is to use multiple Caesar ciphers based on the letters of the keyword.

Let's say we have a plaintext message $P$ consisting of $n$ letters: $P = p_1, p_2, \ldots, p_n$​. We also have a keyword $K$ consisting of $m$ letters: $K = k_1, k_2, \ldots, k_m$​, where $m \leq n$.

To encrypt the message, we repeat the keyword until…

Here is the source code of encryption_decryption.py:

def vigenere_cipher(text, keyword, mode):
    result = ""
    keyword_length = len(keyword)
    keyword = keyword.upper()
    key_index = 0

    for i, char in enumerate(text):
        if char.isalpha():
            ascii_offset = ord('A') if char.isupper() else ord('a')
            keyword_shift = ord(keyword[key_index % keyword_length]) - ord('A')

            if mode == "decrypt":
                keyword_shift = -keyword_shift  # Reverse the shift for decryption

            char = chr((ord(char) - ascii_offset + keyword_shift) % 26 + ascii_offset)
            key_index+=1
        result += char

    return result

# Get mode
while True:
    print('Do you want to (e)ncrypt or (d)ecrypt?')
    response = input('> ').lower()
    if response.startswith('e'):
        action = 'encrypt'
        break
    elif response.startswith('d'):
        action = 'decrypt'
        break
    print('Please enter the letter e or d.')

print("Enter the message.")
message = input('> ')

print("Enter the keyword.")
keyword = input('> ').upper()

# Perform encryption/decryption
result = vigenere_cipher(message, keyword, action)

# Display the result
print(f"Result: {result}")
Enter fullscreen mode Exit fullscreen mode

The vigenere_cipher function performs the encryption or decryption operation based on the provided parameters. It initializes an empty string called result to store the final result. It calculates the length of the keyword and converts it to uppercase.

Next, it iterates through each character in the text input. If the character is a letter, it determines whether it is uppercase or lowercase and assigns an ASCII offset accordingly. It calculates the shift value for the current character based on the corresponding letter in the keyword. If the mode is set to "decrypt," it reverses the shift value.

Then, it applies the shift to the current character by subtracting the ASCII offset, adding the keyword shift, and taking the modulo 26 to wrap around the alphabet. Finally, it converts the shifted value back to a character using the ASCII offset and appends it to the result string. The key_index is incremented to ensure the keyword characters are used cyclically.

After processing all characters in the text, the result string contains the encrypted or decrypted message, depending on the mode.

The code prompts the user to enter the encryption or decryption mode (encrypt or decrypt) and stores the response in the action variable. It keeps asking for input until a valid mode is provided.

Then, it asks the user to enter the message and keyword, storing them in the message and keyword variables, respectively.

The vigenere_cipher function is called with the provided inputs (message, keyword, and action), and the result is stored in the result variable.

The Program in Action

Here is a sample output that we get upon executing the program:

Do you want to (e)ncrypt or (d)ecrypt?
> e
Enter the message.
> Enemy is approaching! Send troops immediately!
Enter the keyword.
> Moonlight
Result: Qbszj qy hibfcnnpouz! Esbq ezuvie wazplohmqzm!

Do you want to (e)ncrypt or (d)ecrypt?
> d
Enter the message.
> Qbszj qy hibfcnnpouz! Esbq ezuvie wazplohmqzm!
Enter the keyword.
> Moonlight
Result: Enemy is approaching! Send troops immediately!
Enter fullscreen mode Exit fullscreen mode

Here the key used is Moonlight.

Conclusion

There are several ways to hack the Vigenère Cipher, such as Kasiski examination, Friedman test, frequency analysis, dictionary attack, etc. However, these are advanced methods and require complex application of combinatorics and statistics. Discussing even one of those would require a separate post. For now we will focus on encryption and decryption. I will surely post a Vigenère hack tutorial in future.

Note: Vigenère Cipher, although complex, is still too easy to break using modern methods and should not be used for serious encryption purposes.

Top comments (0)