• Присоединяйтесь к нашей группе в телеграмм: t.me/TEHADMru

Квадрат Полибия

mexan

Администратор
Сообщения
681
Реакции
81
В криптографии квадрат Полибия (англ. Polybius square), также известный как шахматная доска Полибия — оригинальный код простой замены, одна из древнейших систем кодирования, предложенная Полибием (греческий историк, полководец, государственный деятель, III век до н. э.). Данный вид кодирования изначально применялся для греческого алфавита, но затем был распространен на другие языки.

C#:
using System;

public enum Method
{
    Method1,
    Method2
}

class PolybiusSquare
{
    char[,] square;
    string alphabet;
    Method encryptMethod;

    public PolybiusSquare(string alphabet = null, Method cipherMethod = Method.Method1)
    {
        this.alphabet = alphabet ?? "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
        encryptMethod = cipherMethod;
    }

    //возвращает квадрат Полибия
    char[,] GetSquare(string key)
    {
        var newAlphabet = alphabet;
        //удаляем из алфавита все символы которые содержит ключ
        for (int i = 0; i < key.Length; i++)
        {
            newAlphabet = newAlphabet.Replace(key[i].ToString(), "");
        }

        //добавляем пароль в начало алфавита, а в конец дополнительные знаки
        //для того чтобы избежать пустых ячеек
        newAlphabet = key + newAlphabet + "0123456789!@#$%^&*)_+-=<>?,.";

        //получаем размер стороны квадрата
        //округлением квадратного корня в сторону большего целого числа
        var n = (int)Math.Ceiling(Math.Sqrt(alphabet.Length));

        //создаем и заполняем массив
        square = new char[n, n];
        var index = 0;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (index < newAlphabet.Length)
                {
                    square[i, j] = newAlphabet[index];
                    index++;
                }
            }
        }

        return square;
    }

    //поиск символа в двухмерном массиве
    bool FindSymbol(char[,] symbolsTable, char symbol, out int column, out int row)
    {
        var l = symbolsTable.GetUpperBound(0) + 1;
        for (int i = 0; i < l; i++)
        {
            for (int j = 0; j < l; j++)
            {
                if (symbolsTable[i, j] == symbol)
                {
                    //значение найдено
                    row = i;
                    column = j;
                    return true;
                }
            }
        }

        //если ничего не нашли
        row = -1;
        column = -1;
        return false;
    }

    public string PolibiusEncrypt(string text, string password)
    {
        var outputText = "";
        var square = GetSquare(password);
        switch (encryptMethod)
        {
            case Method.Method1:
                for (int i = 0; i < text.Length; i++)
                {
                    if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
                    {
                        var newRowIndex = rowIndex == square.GetUpperBound(1)
                            ? 0
                            : rowIndex + 1;
                        outputText += square[newRowIndex, columnIndex].ToString();
                    }
                }
                break;

            case Method.Method2:
                var m = text.Length;
                var coordinates = new int[m * 2];
                for (int i = 0; i < m; i++)
                {
                    if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
                    {
                        coordinates[i] = columnIndex;
                        coordinates[i + m] = rowIndex;
                    }
                }

                for (int i = 0; i < m * 2; i += 2)
                {
                    outputText += square[coordinates[i + 1], coordinates[i]];
                }
                break;
        }

        return outputText;
    }

    public string PolybiusDecrypt(string text, string password)
    {
        var outputText = "";
        var square = GetSquare(password);
        var m = text.Length;
        switch (encryptMethod)
        {
            case Method.Method1:
                for (int i = 0; i < m; i++)
                {
                    if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
                    {
                        var newRowIndex = rowIndex == 0
                            ? square.GetUpperBound(1)
                            : rowIndex - 1;
                        outputText += square[newRowIndex, columnIndex].ToString();
                    }
                }
                break;

            case Method.Method2:
                var coordinates = new int[m * 2];
                var j = 0;
                for (int i = 0; i < m; i++)
                {
                    if (FindSymbol(square, text[i], out int columnIndex, out int rowIndex))
                    {
                        coordinates[j] = columnIndex;
                        coordinates[j + 1] = rowIndex;
                        j += 2;
                    }
                }

                for (int i = 0; i < m; i++)
                {
                    outputText += square[coordinates[i + m], coordinates[i]];
                }
                break;
        }

        return outputText;
    }
}
C#:
using System;

class Program
{
    static void Main(string[] args)
    {
        var polybius = new PolybiusSquare();
        Console.Write("Введите текст: ");
        var message = Console.ReadLine().ToUpper();
        Console.Write("Введите пароль(без повторов букв): ");
        var pass = Console.ReadLine().ToUpper();
        var cipherText = polybius.PolibiusEncrypt(message, pass);
        Console.WriteLine("Зашифрованный текст: {0}", cipherText);
        Console.WriteLine("Расшифрованный текст: {0}",
            polybius.PolybiusDecrypt(cipherText, pass));
        Console.ReadLine();
    }
}
programm.top
 
Последнее редактирование:
Верх