отладка — упрощение модульного возведения в степень переполнения стека

Я пытаюсь написать функцию расшифровки для системы шифрования RSA, кажется, все работает нормально для очень небольшие числа, однако иногда вывод просто не корректен (я думаю, что причиной может быть ошибка с плавающей запятой или какое-то переполнение стека).

Процесс, который вызывает у меня проблемы, может быть упрощен до (11 ^ 23) мода 187, но я включу полный код на случай, если кто-нибудь захочет его увидеть. Я знаю, что ответом должно быть 88, поскольку это пример, используемый в Приложении J «Кодовой книги» доктора Саймона Сингха (я также проверял, используя Wolfram Alpha). Тем не менее, я получаю результат 149. Однако, с меньшими числами, это согласуется с Wolfram Alpha.

Я думаю, что мне нужно упростить модульное возведение в степень, используя знания, которые:

a ^ b = a ^ c * a ^ d [где c + d = b]

Тем не менее, я все еще не уверен на 100%, если это проблема, это мой первый переполнение стека? (Я все еще не уверен на 100%, что это значит). Прежде чем кто-нибудь попробует на меня, нет, это не домашняя работа, и мне жаль, если этот вопрос кажется тривиальным. Я открыт для использования gmp.h, если все думают, что это будет слишком сложно, но я бы предпочел этого, если я полностью честен. Мой код приведен ниже (первая часть предназначена для вычисления закрытого ключа, который, я считаю, не имеет отношения к проблеме, с которой я столкнулся, но я включил ее на всякий случай, если я ошибаюсь), я очень надеюсь, что вы, ребята, можете помочь, спасибо Вы очень заранее.

#include <iostream>
#include <math.h>

using namespace std;

unsigned int modinv(unsigned int u, unsigned int v)
{
unsigned int inv, u1, u3, v1, v3, t1, t3, q;
int iter;

u1 = 1;
u3 = u;
v1 = 0;
v3 = v;

iter = 1;

while (v3 != 0)
{

q = u3 / v3;
t3 = u3 % v3;
t1 = u1 + q * v1;

u1 = v1; v1 = t1; u3 = v3; v3 = t3;
iter = -iter;
}

if (u3 != 1)
return 0;
if (iter < 0)
inv = v - u1;
else
inv = u1;
return inv;
}

int main()
{ long unsigned int p = 17;
long unsigned int q = 11;
long unsigned int phi = (p-1)*(q-1);
long unsigned int e = 7;
long unsigned int c = 11;
long unsigned int n = p*q;
long unsigned int d = modinv (e,phi);
{
cout << fmod (pow (c, d), n);
}
return 0;
}

0

Решение

11 ^ 23 — это примерно 2 ^ 80. Только целые числа до 2 ^ 53 могут быть представлены в точности как двойные числа с плавающей точкой. Следовательно, fmod (pow (c, d), n)) возвращает приблизительное значение. Это не подходит в криптографии.

ДОБАВЛЕНО Вы можете выполнить модульное возведение в степень, используя повторное возведение в квадрат. Проверьте статью Википедии о «Вычислении по квадрату»

1

Другие решения

Этот раздел вики о RSA должен помочь:

Пример расшифровки RSA

Обратите внимание, что статья содержит ссылку на китайский алгоритм остатка, который содержит ссылку на алгоритм Евклида: с учетом двух простых чисел, p и q, найти два целых числа a и b, так что ap + bq = 1, что также означает, что (ap) mod q == 1 и (bq) mod p == 1. Что не ясно, так это то, что a или b будут отрицательными, и отрицательное значение должно использоваться в первой части остаточного алгоритма (в статье говорится: используйте значения из алгоритма Евклида). Например, если a отрицательно, то (ap) mod q == 1, но ((a + q) p) mod q также == 1, поэтому и a, и a + q можно считать обратными к p по математике по модулю д.

0

По вопросам рекламы [email protected]