Simplify modular exponentiation C++

穿精又带淫゛_ 提交于 2020-08-20 12:24:54

问题


I am attempting to write the decryption function for an RSA encryption system, everything seemed to be working fine for very small numbers, however sometimes the output just isn't correct (I think that the cause may be a floating point error or some kind of stack overflow).

The process which is causing me problems can be simplified to (11^23) mod 187 but I will include the full code in case anybody wants to see it. I know that the answer should be 88 as it is the example used in Appendix J of "The Code Book" by Dr Simon Singh (I also checked using Wolfram Alpha). However, I get the result of 149. However, with smaller numbers, it agrees with Wolfram Alpha.

My thoughts are that I need to simplify the modular exponentiation using the knowledge that:

a^b = a^c * a^d [ where c + d = b ]

However, I'm still not 100% sure if this is this problem, is this my first ever stack-overflow? (I'm still not 100% sure what that means). Before anybody has a go at me, no this isn't any kind of homework and I'm sorry if this question seems trivial. I am open to using gmp.h if everyone thinks that this would be too difficult to do but I would rather not if I'm entirely honest. My code is below (the first half is to calculate the private key, which I believe is irrelevant to the problem I'm having but I've included it just in case I am wrong), I really hope you guys can help, thank you very much in advance.

#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;
}

回答1:


11^23 is approximately 2^80. Only integers up to 2^53 can be represented exactly as double floating-point numbers. Hence fmod(pow(c, d), n)) returns an approximate value. That is not suitable in cryptography.

ADDED You can do modular exponentiation using repeated squaring. Check Wikipedia's article about "Exponentiation by squaring"




回答2:


This wiki article section about RSA should help:

RSA decryption worked example

Note the article contains a link to Chinese remainder algorithm, which contains a link to Euclid algorithm: given two primes, p and q, find two integers a and b, so that a p + b q = 1, which also means that (a p) mod q == 1 and (b q) mod p == 1. What isn't clear is that either a or b will be negative, and the negative value is to be used in the first part of the remainder algorithm (the article states to use the values from the Euclid algorithm). For example, if a is negative, then (a p) mod q == 1, but ((a+q) p) mod q also == 1, so both a and a+q could be considered to be the inverse of p for math modulo q.



来源:https://stackoverflow.com/questions/22054657/simplify-modular-exponentiation-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!