RSA выбирает целочисленный ключ шифрования С++

В моей криптосистеме RSA я пытаюсь выбрать ключ шифрования e, который относительно прост с phi(n).

phi(n) — это произведение двух чисел, p-1 и q-1, где p и q — простые числа. Эти простые числа генерируются с использованием наивного теста на простоту (да, я знаю, что это неэффективно).

Когда я запускаю свою программу, я получаю следующий вывод:

***** p *****
878222789

***** q *****
851559637

***** n = p x q *****
3523942633

***** phi(n) = (p-1)x(q-1) *****
1794160208

***** e *****
99

***** d *****
47835

Проблема в том, что каждый раз, когда я запускаю эту программу, e всегда оказывается равным 99 или 97. Это единственная константа в этом выводе. Я почти уверен, что мой алгоритм GCD верен. Но это единственная подпрограмма в select_e().

Соответствующие функции:

void select_e(uint &e, const uint phi_n)
{ // e = encryption key
    for(int i=3;i<100;i++) {
        if(gcd(phi_n,i) == 1) {
            e = i;
            break;
            }
    }
    printf("\n***** e *****\n%u\n",e);
}

uint gcd(uint a, uint b) {
    uint temp;
    while (b!=0) {
        temp = b;
        b = a%b;
        a = temp;
    }
    return a;
}

РЕДАКТИРОВАТЬ**************< /em>*********

Итак, я добавил оператор break в select_e(), из-за которого программа выводит обычно значение 3 или 5 для e. Теперь, насколько я понимаю, неудачное расшифрование является результатом целочисленного переполнения из-за умножения двух 32-битных целых чисел и сохранения значения в другом 32-битном целом числе. Поэтому я изменил свою программу, чтобы генерировать меньшие p и q по модулю. Вот эта функция:

void generate_pq(uint &p, uint &q)
{
    srand(time(NULL));
    bool repeat = false;
    printf("\nGenerating keys...\n");

    while(!repeat) {
        p = rand()%100;
        repeat = isPrime(p);
    }
    repeat = false;
    while(!repeat) {
        q = rand()%100;
        repeat = isPrime(q);
    }
    printf("\n***** p *****\n%u\n\n***** q *****\n%u\n",p,q);
}

Теперь проблема в том, что иногда мне везет, и сообщение успешно расшифровывается. В другое время это не работает. Вот пример неудачной расшифровки:

Generating keys...

***** p *****
79

***** q *****
49

***** n = p x q *****
3871

***** phi(n) = (p-1)x(q-1) *****
3744

***** e *****
5

***** d *****
749

Message: fdsa 

Cipher: �/�J

Decrypted Message: �a

Я знаю, что функции расшифровки и шифрования работают. Я протестировал их по отдельности и изучил алгоритмы. Они не являются источником проблемы. Я предоставлю их для потомков, если потребуется.


person Caleb Faruki    schedule 01.12.2013    source источник
comment
Вам может понадобиться break внутри if (gcd...)   -  person erikkallen    schedule 02.12.2013
comment
Все еще не решен. select_e() изменен, чтобы отразить ваше предложение. Спасибо!! Теперь e оказывается равным 3 или некоторому меньшему целому числу.   -  person Caleb Faruki    schedule 02.12.2013
comment
я не могу вспомнить детали здесь (это все по модулю что-то или другое?), но в случае, если это важно, НИКОГДА n выше не является произведением p и q. просто посмотрите на значения.   -  person andrew cooke    schedule 02.12.2013
comment
@andrewcooke: Также НЕТ, что 99 равно 3. Я предполагаю, что вывод, о котором он заявляет ... Я получаю следующий вывод ..., это не что иное, как случайный набор текста на клавиатуре.   -  person President James K. Polk    schedule 02.12.2013
comment
Я отредактировал функцию, когда добавил оператор break. e раньше было 99 или 97, прежде чем я добавил оператор break.   -  person Caleb Faruki    schedule 02.12.2013
comment
значит у тебя проблемы с математикой?   -  person andrew cooke    schedule 02.12.2013
comment
49 не простое число. я получу благодарность на этот раз?   -  person andrew cooke    schedule 02.12.2013


Ответы (1)


Итак, вы выбираете первое возможное число больше двух. Поскольку количество простых делителей любого большого числа чрезвычайно мало по сравнению с самим числом, вы не можете ожидать, что тест if(gcd(phi_n,i) == 1) будет неудачным много раз. Может, один раз не получится, может, два, но я бы даже не стал ждать, пока не выйдет десять раз...

Таким образом, ответом будет случайный выбор i на каждой итерации цикла вместо простого подсчета.


Кстати: ваш вывод забавен в другом отношении: 3523942633 определенно не является произведением 878222788 и 851559636. Не уверен, почему именно, но это выглядит как непреднамеренное усечение из-за использования 32-битных целых чисел...

person cmaster - reinstate monica    schedule 01.12.2013
comment
Как я могу это исправить? Я попытался изменить n & phi(n) на uint64_t в своей программе, но это не сработало. - person Caleb Faruki; 02.12.2013
comment
Добавлено %100 к p и q, которые я генерирую, чтобы они не вызывали переполнения. Любые дальнейшие советы? - person Caleb Faruki; 02.12.2013
comment
@ baph0mt Если вы хотите, чтобы результат умножения не переполнялся, вы должны привести операнды перед умножением, потому что в противном случае умножение приводит к 32-битному значению. т. е. uint32_t a, b; uint64_t result = a*b; усекается, а uint32_t a, b; uint64_t result = (uint64_t)a*(uint64_t)b; нет. - person cmaster - reinstate monica; 02.12.2013