vigenere cipher Algorithm
The Vigenère cipher is a classical encryption algorithm that was invented by Giovan Battista Bellaso in the mid-16th century and later misattributed to Blaise de Vigenère in the 19th century. This symmetric key cipher is a form of polyalphabetic substitution, meaning it utilizes multiple substitution alphabets to encrypt plaintext messages. The Vigenère cipher is an extension of the Caesar cipher, which uses a simple shift of letters within the alphabet, while the Vigenère cipher uses a keyword to determine the shift. This added complexity provides greater security than monoalphabetic substitution ciphers like the Caesar cipher, as it makes frequency analysis more difficult for would-be attackers.
To implement the Vigenère cipher, a tabula recta, also known as the Vigenère square or Vigenère table, is used. This table consists of 26 rows of shifted alphabets, one for each letter of the alphabet. To encrypt a plaintext message, a keyword is chosen, which is then repeated as many times as necessary to match the length of the plaintext. Each letter of the plaintext is then encrypted by finding the intersection of the row corresponding to the keyword letter and the column corresponding to the plaintext letter in the tabula recta. The resulting ciphertext is formed by replacing each plaintext letter with the letter found at the intersection. Decryption is performed by reversing the process, using the keyword to locate the correct row in the tabula recta and finding the corresponding plaintext letter in the column. Despite its increased security compared to monoalphabetic substitution ciphers, the Vigenère cipher is vulnerable to attacks based on Kasiski examination and Friedman tests, which can reveal the keyword length and aid in deciphering the ciphertext.
/**
* Implements a program which encrypts and then decrypts text using Vigenère cipher.
* The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven Caesar ciphers based on the letters of a keyword.
* Refer : https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
*
* Enter the key for encrypting:bacon
* Enter the plain text you want to encrypt:Meet me at the park at eleven am
* Encrypted text: Negh zf av huf pcfx bt gzrwep oz
* Decrypted text: Meet me at the park at eleven am
*/
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
std::string encrypt_data (std::string plain_text, std::string key)
{
std::stringstream encrypted_stream;
unsigned int text_len = plain_text.length();
unsigned int key_len = key.length();
unsigned int char_index = 0;
unsigned int shift_len = 0;
for (unsigned int i = 0; i < text_len; ++i)
{
if (isalpha(plain_text[i]))
{
// If current key char is uppercase, keyReferenceValue would be 'A', otherwise 'a'
// We use keyReferenceValue to convert key char to ascii
//
char keyReferenceValue = (isupper(key[char_index % key_len])) ? 'A' : 'a';
// Similarly, we use referenceValue to convert plain text char to ascii, it would
//
char referenceValue = (isupper(plain_text[i])) ? 'A' : 'a';
shift_len = key[char_index % key_len] - keyReferenceValue;
encrypted_stream << char(((plain_text[i] - referenceValue + shift_len) % 26) + referenceValue);
++char_index;
}
else
{
// for non alpha chars, we don't encrypt and keep them as it is.
encrypted_stream << plain_text[i];
}
}
return encrypted_stream.str();
}
std::string decrypt_data(std::string encrypted_text, std::string key)
{
std::stringstream decrypted_stream;
unsigned int text_len = encrypted_text.length();
unsigned int key_len = key.length();
unsigned int char_index = 0;
unsigned int shift_len = 0;
for (unsigned int i = 0; i < text_len; ++i)
{
if (isalpha(encrypted_text[i]))
{
// If current key char is uppercase, keyReferenceValue would be 'A', otherwise 'a'
// We use keyReferenceValue to convert key char to ascii
//
char keyReferenceValue = (isupper(key[char_index % key_len])) ? 'A' : 'a';
// Similarly, we use referenceValue to convert plain text char to ascii, it would
//
char referenceValue = (isupper(encrypted_text[i])) ? 'A' : 'a';
shift_len = key[char_index % key_len] - keyReferenceValue;
decrypted_stream << char((((encrypted_text[i] - referenceValue) + (26 - shift_len)) % 26) + referenceValue);
++char_index;
}
else
{
// We don't encrypt non-alpha chars, so keeping them as it is.
decrypted_stream << encrypted_text[i];
}
}
return decrypted_stream.str();
}
int main()
{
std::string plain_text, encrypted_text;
std::string key;
std::cout << "Enter the key for encrypting:";
std::cin >> key;
std::cin.clear();
std::cin.sync();
std::cin.ignore();
std::cout << "Enter the plain text you want to encrypt:";
std::getline(std::cin, plain_text);
encrypted_text = encrypt_data(plain_text, key);
std::cout << "Encrypted text: " << encrypted_text << std::endl;
plain_text.clear();
plain_text = decrypt_data(encrypted_text, key);
std::cout << "Decrypted text: " << plain_text << std::endl;
return 0;
}