Ошибка расшифровки RSA

0

Я пытаюсь реализовать схему шифрования RSA, но, хотя мои зашифрованные значения кажутся правильными, дешифрованные не являются. Основываясь на значениях p, q и т.д., Которые я получаю, кажется, что часть вычисления (IE, сложная часть) прекрасна, и сообщение, похоже, правильно шифруется (на всякий случай я включаю часть шифрования как ну хотя). Обратите внимание, что я должен делать это без каких-либо библиотек (я уже писал это с помощью GMP), поэтому я использую нецелесообразно небольшие числа.

int main()
{
    ...
    vector<uint64_t> encrypted = doEncrypt(e, n);
    doDecrypt(d, n, encrypted);
}
vector<uint64_t> doEncrypt(unsigned int e, unsigned int n)
{
    string message;
    vector<uint64_t> encrypted;
    cout << "Public key is <" << e << ", " << n << ">.\nPlease enter a message to encrypt: ";
    getline(cin, message);
    for (unsigned int i = 0; i < message.length(); i++)
        encrypted.push_back(encrypt(message[i], e, n));
    return encrypted;
}
uint64_t encrypt(char message, unsigned e, unsigned int n)
{
    int toencrypt = (int)message;
    cout << toencrypt << ' ';
    uint64_t result = pow64(toencrypt, e);
    return result%n;
}
void doDecrypt(unsigned int d, unsigned int n, vector<uint64_t> encrypted)
{
    cout << "Encrypted message is: ";
    for (unsigned int i = 0; i < encrypted.size(); i++)
    cout << encrypted[i] << ' ';
    cout << "\nDecrypted message is: ";
    char out;
    for (unsigned int i = 0; i < encrypted.size(); i++){
        decrypt(out, encrypted[i], d, n);
        cout << out << ' ';//This is only for diagnostics, I will
                       //take out the printing of the decrypted
                       //number and space later
    }
    cout << endl;
}

void decrypt(char& decrypted, uint64_t message, unsigned int d, unsigned int n)
{
    uint64_t decrypt = (pow64(message, d)%n);
    cout << decrypt;
    decrypted = (char)decrypt;
}

uint64_t pow64(uint64_t base, unsigned int ex)
{
    uint64_t back = 1;
    for (unsigned int i = 0; i < ex; i++)
        back = back * base;
    return back;
}

Пример вывода:

p = 23
q = 23
n = 529
phi_n = 484
e = 9
d = 269
Открытый ключ <9, 529>.
Введите сообщение для шифрования: dog
100 111 103 Зашифрованное сообщение: 515 33 295
Расшифрованное сообщение: 523 417▒ 364l

  • 0
    зашифрованное сообщение содержит нулевой терминатор? Просто угадаю ...
  • 0
    Даже если бы в векторе было дополнительное значение, я думаю, что остальные должны работать.
Показать ещё 2 комментария
Теги:
rsa

1 ответ

1

Ваша проблема в том, что p == q, поэтому n - идеальный квадрат, а не произведение двух простых чисел, что означает, что ваш расчет phi (n) неверен. phi (p ^ 2) == p * (p-1), где p - простое число. Поэтому, если вы измените свой код на использование phi (n) == 506 и d == 225, он должен работать.

Или выбрали разные p и q.

Еще одна ошибка, о которой стоит беспокоиться при тестировании кода с небольшими штрихами - шифрование/дешифрование завершится неудачно, если значение открытого текста будет кратно p или q. Это очень маловероятно, если вы используете реальные значения (256 бит или более) для p и q, но может произойти случайно с такими малыми значениями. Вероятность удара этой проблемы такая же, как вероятность того, что противник случайно угадает ваши частные факторы.

Третья ошибка, которая может произойти, состоит в том, что публичный экспонент e вы выберете, не должен иметь каких-либо общих факторов с phi (n), или не существует действительного показателя d декодирования. Опять же, это не проблема с "настоящими" RSA-ключами, поскольку (p-1)/2 и (q-1)/2 должны быть первичными, так как до тех пор, пока e нечетно, вероятность того, что не будет иметь действительного расшифровки ключ исчезающе мал.

редактировать

Проблема с вашим кодом заключается в том, что ваша процедура pow64 будет легко переполняться (515 ^ 269 - более 2000 бит). Попробуйте использовать:

uint64_t pow64(uint32_t base, uint32_t ex, uint32_t n)
{
    uint64_t back = 1;
    for (unsigned int i = 0; i < ex; i++)
        back = (back * base) % n;
    return back;
}

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

uint64_t pow64(uint32_t base, uint32_t ex, uint32_t n)
{
    uint64_t back = 1;
    for (uint64_t i = 1; i <= ex; i <<= 1) {
        if (i & ex)
            back = (back * base) % n;
        base = ((uint64_t)base * base) % n; }
    return back;
}
  • 0
    Р и q, будучи одинаковыми, были одним конкретным прогоном, в этом прогоне я выбирал их значения случайным образом (или, более конкретно, выбирал случайное минимальное число и находил следующее простое число), но позже я установил их значения на 7 и 37 (так n равно 259, что немного больше, чем наибольшее значение символа 255), и возникает та же проблема.
  • 0
    RSA не имеет ограничений на m, кратный p или q, дешифрование будет работать как обычно (при условии p! = Q, как здесь).
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню