Как реализовать C=m^e mod n для огромных чисел?

Я пытаюсь выяснить, как реализовать RSA crypto с нуля (только для интеллектуального упражнения), и я застрял на этом пункте:

для шифрования, c = me mod n

теперь, e обычно 65537. m и n-1024-разрядные целые числа (например, 128-байтовые массивы). Очевидно, что это слишком много для стандартных методов. Как бы вы это сделали?

Я читал немного об экспоненциальности здесь, но он просто не нажимает на я:

Википедия-возведение в квадрат

Эта Глава (см. раздел 14.85)

спасибо.

edit: также найдено это-это больше, что я должен смотреть? Википедия - Модульное Возведение В Степень

4 ответов


возведение в квадрат:

возьмем пример. Вы хотите найти 1723. Обратите внимание, что 23 - это 10111 в двоичном. Давайте попробуем построить его слева направо.

           // a      exponent in binary

a = 17     //17^1          1

a = a * a  //17^2         10

a = a * a  //17^4        100
a = a * 17 //17^5        101

a = a * a  //17^10      1010
a = a * 17 //17^11      1011

a = a * a  //17^22     10110
a = a * 17 //17^23     10111

когда вы квадрат, вы удваиваете показатель (сдвиг влево на 1 бит). Когда вы умножаете на m, вы добавляете 1 к показателю.

если вы хотите уменьшить по модулю n, вы можете сделать это после каждого умножения (а не оставлять его до конца, что бы сделать цифры становятся очень большими).

65537 составляет 10000000000000001 в двоичном формате, что делает все это довольно легко. Это в основном

a = m
repeat 16 times:
    a = a * a
    a = a mod n
a = a * m
a = a mod n

где, конечно, a, n и m - "большие целые числа". a должен быть не менее 2048 бит, поскольку он может быть таким же большим ,как (n-1)2.


для эффективного алгоритма вам нужно объединить возведение в квадрат с повторным применением mod после каждого шага.

для нечетных e это:

me mod n = m ⋅ me-1 mod n

даже e:

me mod n = (me / 2 mod n)2 mod n

С m1 = m в качестве базового случая это определяет рекурсивный способ эффективного модульного возведения в степень.

но даже с таким алгоритмом, как этот, потому что m и n будет очень большим, вам все равно нужно будет использовать тип / библиотеку, которая может обрабатывать целые числа таких размеров.


result = 1
while e>0:
  if (e & 1) != 0:
    result = result * m
    result = result mod n
  m = m*m
  m = m mod n
  e = e>>1
return result

это проверяет биты в экспоненте, начиная с наименее значимого бита. Каждый раз, когда мы немного поднимаемся, это соответствует удвоению мощности m-следовательно, мы сдвигаем e и Квадрат m. Результат получает только мощность M умножается, если показатель имеет 1 бит в этой позиции. Все умножения должны быть уменьшены mod n.

в качестве примера рассмотрим m^13. 11 = 1101 в двоичном формате. так что это то же самое, что m^8 * m^4 * m. Обратите внимание на полномочия 8,4, (не 2), 1, которые совпадают с биты 1101. А затем вспомните, что m^8 = (m^4)^2 и m^4 = (m^2)^2.


Если g(x) = x mod 2^k быстрее рассчитать для вашей библиотеки bignum, чем f(x) = x mod N для N, не делимого на 2, затем рассмотрите возможность использования умножение. При использовании с модульным возведением в степень, оно избегает высчитать модульное N на каждом шаге, вам как раз нужно сделать "Montgomeryization" / "un-Montgomeryization" в начале и конце.