В данной статье рассмотрим шифр Виженера. Будет описан алгоритм и написана программа на языке C#, реализующая классический шифр Виженера и шифрование гаммированием.
Шифр Виженера. Описание алгоритма
Шифрование методом Виженера производится по формуле:
где ci – символ закодированного сообщения, pi – символ исходного сообщения, ki – символ ключа, N – мощность алфавита (количество символов в алфавите).
Символы ключа накладываются на шифруемое сообщение циклически. Например, пусть исходное сообщение: программирование на c#, а ключ = vscode, тогда на данное сообщение ключ наложиться следующим образом:
Расшифровка методом Виженера производится по формуле:
При шифровании гаммированием в качестве ключа используется последовательность символов сгенерированная с помощью генератора псевдослучайных чисел и по длине равная исходному сообщению. Псевдослучайные числа генерируются на основе заданного (всегда одинакового) начального параметра, поэтому последовательность во всех случаях получается идентичной.
Шифр Виженера. Реализация
Пусть алфавит задан в виде массива символов:
| 
					 1 2 3 4 5  | 
						char[] characters = new char[] { 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И',                                                 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С',                                                  'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ь', 'Ы', 'Ъ',                                                 'Э', 'Ю', 'Я', ' ', '1', '2', '3', '4', '5', '6', '7',                                                 '8', '9', '0' };  | 
					
Тогда мощность алфавита будет равна:
| 
					 1  | 
						N = characters.Length;  | 
					
Приведем реализацию метода на языке C#, шифрующего строку методом Виженера.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25  | 
						//зашифровать private string Encode(string input, string keyword) {     input = input.ToUpper();     keyword = keyword.ToUpper();     string result = "";     int keyword_index = 0;     foreach (char symbol in input)     {         int c = (Array.IndexOf(characters, symbol) +             Array.IndexOf(characters, keyword[keyword_index])) % N;         result += characters[c];         keyword_index++;         if ((keyword_index + 1) == keyword.Length)             keyword_index = 0;     }     return result; }  | 
					
На вход поступает строка, которую нужно зашифровать (input) и ключ (keyword).
Теперь приведем реализацию метода, расшифровывающего строку.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25  | 
						//расшифровать private string Decode(string input, string keyword) {     input = input.ToUpper();     keyword = keyword.ToUpper();     string result = "";     int keyword_index = 0;     foreach (char symbol in input)     {         int p = (Array.IndexOf(characters, symbol) + N -             Array.IndexOf(characters, keyword[keyword_index])) % N;         result += characters[p];         keyword_index++;         if ((keyword_index + 1) == keyword.Length)             keyword_index = 0;     }     return result; }  | 
					
Кроме того, для гаммирования понадобится генерирование псевдослучайного ключа. Вот метод, который делает это:
| 
					 1 2 3 4 5 6 7 8 9 10 11  | 
						private string Generate_Pseudorandom_KeyWord(int length, int startSeed) {     Random rand = new Random(startSeed);     string result = "";     for (int i = 0; i < length; i++)         result += characters[rand.Next(0, characters.Length)];     return result; }  | 
					
length — нужная длина ключа. startSeed — число, которым инициализируется генератор случайных чисел. Это число должно быть всегда одинаковым, таким образом и ключ будет всегда один и тот же.
Программа имеет следующий интерфейс:
Код кнопки «Зашифровать» приведен ниже.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  | 
						//зашифровать private void buttonEncrypt_Click(object sender, EventArgs e) {     if (radioButtonGamma.Checked)     {         string s;         StreamReader sr = new StreamReader("in.txt");         StreamWriter sw = new StreamWriter("out.txt");         while (!sr.EndOfStream)         {             s = sr.ReadLine();             sw.WriteLine(Encode(s, Generate_Pseudorandom_KeyWord(s.Length, 100)));         }         sr.Close();         sw.Close();     }     else     {         if (textBoxKeyWord.Text.Length > 0)         {             string s;             StreamReader sr = new StreamReader("in.txt");             StreamWriter sw = new StreamWriter("out.txt");             while (!sr.EndOfStream)             {                 s = sr.ReadLine();                 sw.WriteLine(Encode(s, textBoxKeyWord.Text));             }             sr.Close();             sw.Close();         }         else             MessageBox.Show("Введите ключевое слово!");     } }  | 
					
Происходит чтение данных из файла in.txt, выполняется шифрование (в зависимости от выбранного radioButton) и запись результата в файл out.txt.
Код кнопки «Расшифровать» приводится далее.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  | 
						//расшифровать private void buttonDecipher_Click(object sender, EventArgs e) {     if (radioButtonGamma.Checked)     {         string s;         StreamReader sr = new StreamReader("in.txt");         StreamWriter sw = new StreamWriter("out.txt");         while (!sr.EndOfStream)         {             s = sr.ReadLine();             sw.WriteLine(Decode(s, Generate_Pseudorandom_KeyWord(s.Length, 100)));         }         sr.Close();         sw.Close();     }     else     {         if (textBoxKeyWord.Text.Length > 0)         {             string s;             StreamReader sr = new StreamReader("in.txt");             StreamWriter sw = new StreamWriter("out.txt");             while (!sr.EndOfStream)             {                 s = sr.ReadLine();                 sw.WriteLine(Decode(s, textBoxKeyWord.Text));             }             sr.Close();             sw.Close();         }         else             MessageBox.Show("Введите ключевое слово!");     } }  | 
					
Демонстрация работы программы (шифрование и расшифровка данных методом Виженера) приведена на скриншоте ниже.
Скачать исходник программы, рассмотренной в данной статье, можно, нажав на кнопку.
Скачать исходник
Поделиться в соц. сетях:



без кодировки вместо букв — нули
//зашифровать
private void buttonEncrypt_Click(object sender, EventArgs e)
{
if (radioButtonGamma.Checked)
{
string s;
StreamReader sr = new StreamReader(«in.txt»,Encoding.GetEncoding(1251));
StreamWriter sw = new StreamWriter («out.txt»);
далее по тексту.
Так происходит, когда входной файл «in.txt» создается в Блокноте. По умолчанию Блокнот записывает файл в кодировке ANSI, поэтому, при чтении файла, в StreamReader нужно её указать явно.
Если создать входной файл в кодировке UTF-8 без BOM (например, с помощью программы Notepad++), то указывать ничего не потребуется.
спасибо,понятно
Объясните пожалуйста как происходит действие шифрования. В строку ключа я ввожу слово, но ничего не происходит.
Исходный текст для шифрования должен быть в текстовом файле. Результат также заносится в текстовый файл.
Спасибо)
При шифровании с ключом алфавит в процессе шифрования сдвигается, как я понимаю, на 1 символ. А как сделать сдвиг на сколько я хочу?
Не на один, а на число равное номеру символа в алфавите из ключа, накладываемого на шифруемый символ.
а как можно сделать чтобы можно было выбирать файл для записи и считывания? т.е. вместо in и out выбрать свои файлы?
Посмотрите здесь и сделайте подобно: https://vscode.ru/prog-lessons/kak-zagruzit-kartinku-v-picturebox.html