Как вычислить модульную мультипликативную инверсию для аффинного шифра

Я пытаюсь создать небольшое программное обеспечение, которое выполняет аффинный шифр, что означает, что K1 и количество букв в алфавите (используя m для этого числа) должны быть взаимно простыми. , то есть gcd(k1, m) == 1.

В основном это так:

У меня есть открытый текст: привет

У меня К1: 7

У меня К2: 5

Открытый текст в числовом формате: 8 5 25

8 - от h (позиция в алфавите) и **5 25** идет одинаково для e и y

Зашифровано: 7 13 18

Какая формула:

k1 * 8 + k2 по модулю 27 = 7

k1 * 5 + k2 по модулю 27 = 13

1 лиц * 25 + лиц 2 по модулю 27 = 18

У меня есть функция, которая шифрует это, но я не знаю, как расшифровать.

Например у меня 7 для h. Я хочу снова получить число 8, зная 7, k1 и k2.

У вас есть идеи?

Некоторая функция, в которой вы вводите k1, k2, результат (например, 7 для h), и она возвращает мне 8, но я действительно не знаю, как это изменить.

Функция шифрования такова:

public List<int> get_crypted_char(string[] strr)
        {
            List<int> l = new List<int>();
            int i;
            for (i = 0; i < strr.Length; i++)
            {
                int ch = int.Parse(strr[i]);
                int numberback = k1 * ch + 5;
                numberback = (numberback % 27);
                l.Add(numberback);
            }
            return l;
        }

Где: string[] strr — это строка, содержащая открытый текст. Пример функции: get_crypted_char({"e","c","b"})

Результатом будет такой список {"5","3","2"}

ОБНОВЛЕНИЕ: Вот ссылка из википедии об этом шифровании, а также о расшифровке, но... я не очень понимаю, "как" http://en.wikipedia.org/wiki/Affine_cipher


person icebox19    schedule 30.10.2013    source источник
comment
Ваш вопрос не ясен, ИМО..   -  person Soner Gönül    schedule 30.10.2013
comment
У вас есть код шифрования? Я думаю, что это легче читать.   -  person Stefan    schedule 30.10.2013
comment
Об этом задавали и отвечали в прошлом: stackoverflow.com/a/10133236/146205. Нет никакого реального способа получить это обратно, так как, например, 8 mod 3 и 5 mod 3 равны 2.   -  person Jensen    schedule 30.10.2013
comment
Знание результата операции мода не поможет вам найти операнды. Например, 61 mod 27 = 7, а также 34 mod 27 = 7 или даже 7 mod 27 = 7. Так как же узнать, какая из миллиона возможностей является правильной?   -  person Giannis Paraskevopoulos    schedule 30.10.2013
comment
По ссылке есть алгоритм расшифровки. И почему вы используете 27?   -  person paparazzo    schedule 30.10.2013
comment
в моем случае я должен использовать 27. В ссылке, в алгоритме расшифровки я не знаю, откуда берется 21. вроде как в -1, но не знаю откуда   -  person icebox19    schedule 30.10.2013
comment
@icebox19 icebox19 Посмотрите на мой ответ, это рабочее решение. Но, пожалуйста, пройдите уроки математики, может быть, вам не стоит иметь дело с шифрами? :)   -  person flindeberg    schedule 30.10.2013
comment
@JensenSomers Это совершенно другой случай, в этом случае значения взаимно просты.   -  person flindeberg    schedule 30.10.2013
comment
@jyparask Они взаимно просты, как указано в алгоритме. (Но не в шапке).   -  person flindeberg    schedule 30.10.2013


Ответы (3)


Это невозможно (в общем случае для аффинного шифра см. обновление ниже). Именно поэтому модульная работа так часто используется в алгоритмах безопасности - она ​​необратима. Но почему бы нам не попробовать?

result = (k1 * input + k2) % 27 (*1)

Возьмем первую букву:

result = (7 * 8 + 5) % 27 = 7

Это классно. Теперь, потому что мы сказали, что:

result = (k1 * input + k2) % 27

также верно следующее:

k1 * input + k2 = 27 * div + result (*2)

где

div = (k1 * input + k2) / 27 (integral division)

Это вполне очевидно (если a % b = c, то a = b*n + c, где n — результат целочисленного деления a/b).

Вы знаете значения k1 (что равно 7), k2 (5) и результат (7). Итак, когда мы помещаем эти значения в (*2), мы получаем следующее:

7 * input + 5 = 27 * div + 7 //You need to solve this

Как вы можете видеть, это невозможно решить, потому что вам нужно знать также результат целочисленного деления - переводя это на язык вашей функции, вам нужно значение

numberback / 27

что неизвестно. Итак, ответ таков: вы не можете отменить результаты своей функции, используя только вывод, который она возвращает.


** ОБНОВИТЬ **


Я слишком сосредоточился на заголовке вопроса, поэтому ответ выше не совсем правильный. Решил не удалять, однако, а написать обновление.

Таким образом, ответ для вашего конкретного случая (аффинный шифр): ДА, вы можете обратить его вспять.

Как вы можете видеть в вики, функция дешифрования для аффинного шифра для следующей функции шифрования:

E(input) = a*input + b mod m

определяется как:

D(enc) = a^-1 * (enc - b) mod m

Единственной возможной проблемой здесь может быть вычисление a^-1, которое является модульно-мультипликативным обратным.

Прочитайте об этом на wiki, я приведу только пример.

В вашем случае a = k1 = 7 и m = 27. Итак:

7^-1 = p mod 27
7p = 1 mod 27

Другими словами, вам нужно найти p, который удовлетворяет следующему: 7p % 27 = 1. p можно вычислить с помощью расширенного алгоритма Евклида, и я вычислил его равным 4 (4 * 7 = 28, 28 % 27 = 1).

Проверьте, можете ли вы сейчас расшифровать ваш вывод:

E(8) = 7*8 + 5 mod 27 = 7

D(7) = 4 * (7 - 5) mod 27 = 8

Надеюсь, это поможет :)

person Mateusz Grzejek    schedule 30.10.2013
comment
@icebox19 icebox19 Однако ответ неверен. Шифр требовал взаимно простых чисел. - person flindeberg; 30.10.2013
comment
Вы делаете то же предположение, что и @Stefan, числа не случайны. k1 и m (27) взаимно просты, не забывайте об этом. - person flindeberg; 30.10.2013

Обратите внимание, что другие ответы не учитывают, что рассматриваемый алгоритм - это аффинный шифр, т.е. есть некоторые условия, наиболее важным из которых является взаимно простое состояние k1 и m.

В вашем случае это будет:

m = 27; // letters in your alphabet
k1 = 7; // coprime with m
k2 = 5; // no reqs here, just that a value above 27 is the same as mod 27 of that value

int Encrypt(int letter) {
  return ((letter * k1) + k2) % m;
}

int Decrypt(int letter) {
  return ((letter - k2) * modInverse(k1, m)) % m;
}

Tuple<int, Tuple<int, int>> extendedEuclid(int a, int b)
{
  int x = 1, y = 0;
  int xLast = 0, yLast = 1;
  int q, r, m, n;
  while (a != 0)
  {
    q = b / a;
    r = b % a;
    m = xLast - q * x;
    n = yLast - q * y;
    xLast = x; yLast = y;
    x = m; y = n;
    b = a; a = r;
  }
  return new Tuple<int, Tuple<int, int>>(b, new Tuple<int, int>(xLast, yLast));
}

int modInverse(int a, int m)
{
  return (extendedEuclid(a, m).Item2.Item1 + m) % m;
}

Реализация ModInverse взята с http://comeoncodeon.wordpress.com/2011/10/09/modular-multiplicative-inverse/.

person flindeberg    schedule 30.10.2013

Я создал программу, которая расскажет модульную инверсию чего-то. Я позволю тебе использовать его. Он размещен ниже.

# Cryptomath Module


def gcf(a, b):
    # Return the GCD of a & b using Euclid's Algorithm
    while a != 0:
        a, b = b % a, a
    return b


def findModInverse(a, m):
    # Return the modular inverse of a % m, which is
    # the number x such that a*x % m = 1

    if gcf(a, m) != 1:
        return None # No mode inverese if a & m aren't relatively prime

    # Calculate using the Extended Euclidean Algorithm:
    u1, u2, u3 = 1, 0, a
    v1, v2, v3 = 0, 1, m
    while v3 != 0:
        q = u3 // v3 # // is the integer division operator
        v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q *
v3), v1, v2, v3
    return u1 % m

Примечание. Модульная инверсия находится с использованием расширенного алгоритма Евклида. Вот запись об этом в Википедии: http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm .

Примечание. Это необходимо импортировать как модуль для использования. Надеюсь, поможет.

person Community    schedule 15.02.2015