Контакты Поиск
26.02.2019 07:07
Occul
 
Шифр Виженера часто называют следующим шагом развития Шифра Цезаря. Но хотя этот алгоритм, безусловно, является более надежным и безопасным по сравнению с тем же шифром цезаря, его все же довольно просто взломать. Данный шифр назван в честь французского дипломата Блеза Виженера. Историю его возникновения можете почитать на Википедии, там данная статья является достоверной, а мне ее расписывать немного лень...

Концепция алгоритма
Как и в других алгоритмах шифрования, он принимает на вход текст и ключ, обрабатывает и выводит зашифрованный текст. Но в отличие от шифра Цезаря, ключ которого был ограничен числом от 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;
}

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.