Шифр Виженера часто называют следующим шагом развития Шифра Цезаря. Но хотя этот алгоритм, безусловно, является более надежным и безопасным по сравнению с тем же шифром цезаря, его все же довольно просто взломать. Данный шифр назван в честь французского дипломата Блеза Виженера. Историю его возникновения можете почитать на Википедии, там данная статья является достоверной, а мне ее расписывать немного лень...
Концепция алгоритма
Как и в других алгоритмах шифрования, он принимает на вход текст и ключ, обрабатывает и выводит зашифрованный текст. Но в отличие от шифра Цезаря, ключ которого был ограничен числом от 0 до 25, этот шифр принимает в качестве ключа слово(фразу), каждая буква которого будет являться отдельным ключом для сдвига соответствующей буквы во входной фразе(далее на примере покажу, станет все понятно:)
Те Шифр Виженера состоит из последовательности нескольких шифров Цезаря с различными значениями сдвига. Для шифрования может использоваться таблица алфавитов, называемая квадратом Виженера. Применительно к латинскому алфавиту таблица Виженера составляется из строк по 26 символов, причём каждая следующая строка сдвигается на несколько позиций. Таким образом, в таблице получается 26 различных шифров Цезаря.
К примеру входной текст будет, эммм: Cheburnet
А ключом будет являться: Putinchmo
То на выходе мы получим: Rbxjhtuqh
Когда наш исходный текст больше ключа, то ключ дописывается справа, чтобы соответствовать размеру текста:
Текст: roskomnazdor
Ключ: sosetsosetso
Результат: jckohebsdwgf
Ну, вот вообщем-то и все, что нам нужно знать для успешной реализации алгоритма)
Реализация Шифра Виженера на c++
Итак нам необходимо написать функцию которая, будет принимать в качестве аргументов исходный текст и ключ, а возвращать уже зашифрованный текст.
А сам шифрование каждой отдельной буквы при прогоне текста по циклу будет выглядеть в виде подобного выражения: (с - буква из исходного текста)
c = (((c - 'a') + (key[i++ % key.size()] - 'a')) % 26) + 'a';
Что очень напоминает выражение, которое применяли в шифре Цезаря, не так ли?)
А сама функция будет выглядеть следующим образом:
Код:
string encrypt(string text, string key)
{
string result = text;
int i = 0;
for (auto& c : result)
{
/*проверяем буквы на нижний или верхний регистр*/
if (islower(c))
{
c = (((c - 'a') + (key[i++ % key.size()] - 'a')) % 26) + 'a';
}
else if (isupper(c))
{
c = (((c - 'A') + (key[i++ % key.size()] - 'A')) % 26) + 'A';
}
}
return result;
}
Если вдруг не понимаете реализацию цикла, то загуглите что-то типа "цикл for в 11 стандарте с++"...)
Теперь нам осталось написать функцию для дешифровки закодированного сообщения, имея ключ.
Что нам для этого нужно... Пример
Enc: H I
Key: B B
Dec: I J
Теперь объясню, что я написал) Если мы зашифруем с помощью ключа B наш исходный текст, то мы получим I, а если мы также попробуем зашифровать получившиеся I, то мы по существу сместим наш исходный текст. Поэтому, если мы сместим наш зашифрованный текст с помощью алфавитного дополнения 25, мы вернемся к нашему тексту.
Должно получится так:
Код:
string decrypt(string str, string key)
{
string k = key;
for (auto& c : k)
{
c = tolower(c) - 'a' - 1;
c = 'z' - c;
}
return encrypt(str, k);
}
Вот вообщем и все...
Полная запись реализации будет примерно такой:
Код:
#include <iostream>
#include <string>
using namespace std;
string encrypt(string text, string key)
{
string result = text;
int i = 0;
for (auto& c : result)
{
if (islower(c))
П{
c = (((c - 'a') + (key[i++ % key.size()] - 'a')) % 26) + 'a';
}
else if (isupper(c))
{
c = (((c - 'A') + (key[i++ % key.size()] - 'A')) % 26) + 'A';
}
}
return result;
}
string decrypt(string str, string key)
{
string k = key;
for (auto& c : k)
{
c = tolower(c) - 'a' - 1;
c = 'z' - c;
}
return encrypt(str, k);
}
int main()
{
string text, key;
getline(cin, text);
getline(cin, key);
string cipher(encrypt(text, key));
cout << cipher << endl;
cout << "\n" << decrypt(cipher, key) << endl;
}