Как реализовать 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" в начале и конце.