Шифрування Віженера

Шифр Віженера – алгоритм шифрування текстових даних за допомогою ключового слова.

Опис алгоритму

Шифрування Віженера можна уявити як декілька шифрів Цезаря з різними ключами. Найпростіше шифри представити у вигляді таблиці, для англійського алфавіту ми отримаємо 26 рядків шифру Цезаря, в кожному рядку зсув на одиницю більше попереднього:

Математично шифр Віженера можна описати наступними формулами:

  • Encrypt(mn) = (Q + mn + kn) % Q;
  • Decrypt(cn) = (Q + cn - kn) % Q.

де mn - позиція символу відкритого тексту, kn - позиція символу ключа шифрування, Q - кількість букв в алфавіті, cn - позиція символу зашифрованого тексту.

Реалізація шифрування Віженера

using System;

public class VigenereCipher
{
    const string defaultAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    readonly string letters;

    public VigenereCipher(string alphabet = null)
    {
        letters = string.IsNullOrEmpty(alphabet) ? defaultAlphabet : alphabet;
    }

    //генерування повторюваного пароля
    private string GetRepeatKey(string s, int n)
    {
        var p = s;
        while (p.Length < n)
        {
            p += p;
        }

        return p.Substring(0, n);
    }

    private string Vigenere(string text, string password, bool encrypting = true)
    {
        var gamma = GetRepeatKey(password, text.Length);
        var retValue = "";
        var q = letters.Length;

        for (int i = 0; i < text.Length; i++)
        {
            var letterIndex = letters.IndexOf(text[i]);
            var codeIndex = letters.IndexOf(gamma[i]);
            if (letterIndex < 0)
            {
                //якщо літера не знайдена, додаємо її в незмінному вигляді
                retValue += text[i].ToString();
            }
            else
            {
                retValue += letters[(q + letterIndex + ((encrypting ? 1 : -1) * codeIndex)) % q].ToString();
            }
        }

        return retValue;
    }

    //шифрування тексту
    public string Encrypt(string plainMessage, string password)
        => Vigenere(plainMessage, password);

    //дешифрування тексту
    public string Decrypt(string encryptedMessage, string password)
        => Vigenere(encryptedMessage, password, false);
}

class Program
{
    static void Main(string[] args)
    {
        //передаємо в конструктор класу літери українського алфавіту
        var cipher = new VigenereCipher("АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ");
        Console.Write("Введіть текст: ");
        var inputText = Console.ReadLine().ToUpper();
        Console.Write("Введіть ключ: ");
        var password = Console.ReadLine().ToUpper();
        var encryptedText = cipher.Encrypt(inputText, password);
        Console.WriteLine("Зашифроване повідомлення: {0}", encryptedText);
        Console.WriteLine("Розшифроване повідомлення: {0}", cipher.Decrypt(encryptedText, password));
        Console.ReadLine();
    }
}

Результат роботи програми:

Дивіться також: